Pomoc - Szukaj - Użytkownicy - Kalendarz
Pełna wersja: [PHP][MySQL]Prawidłowo wyświetlana strona, dziwne źródło strony
Forum PHP.pl > Forum > Przedszkole
Andrzej.W.
Witam.
Mam oto następującą zagadkę.
Zacząłem sobie pisać małą aplikację, do własnego użytku i dla poćwiczenia, ale chciałbym, aby kod był zrobiony wg. prawideł. No i dzieje się rzecz dziwna, bo kod się realizuje, strona wyświetla się prawidłowo, ale w źródle strony zwraca tylko pierwsze include i wartość "die" pierwszego zapytania update z poniższego kodu.
1. Sprawdziłem wartość wszystkich zmiennych pobieranych z formularza, lub też z bazy danych za pomocą var_dump() i zwracają one wartości żądane.
2. Mało tego, wszystkie zapytania realizują się prawidłowo, wszystko ląduje w bazie danych tak, jak tego oczekuję.

Chciałem tylko dodać, że kod nie jest skończony, chciałem sobie najpierw rozpisać wszystkie zapytania, a dopiero potem go uzbroić w filtrację i całą resztę.

3. Idąc zgodnie z tym, co podaje wikibooks w temacie PDO(pierwszy raz próbuje zastosować to rozwiązanie) powstawiałem po każdym query(); poniższe polecenia:
$stmt -> closeCursor();
unset($stmt);

kod testowany z nimi i bez nich. Rezultat nadal taki sam.

4. Przetestowałem każde z zapytań w czystym sql podstawiając wartości zmiennych używanych w zapytaniach, również nie zwracają żadnego błędu.

Kod
<?php
include('../templates/header.tpl');

$pdo = new PDO('mysql:host=localhost;dbname=cash', 'root', 'hasło') or die('zonk');

/*przychody*/

/*Wycią…gam id kategorii przychody potrzebne do tabeli revenues*/
$stmt = $pdo -> query("SELECT id_revenue_category FROM revenue_categories WHERE revenue_name='{$_POST['revenue_name']}'") or die('zły select przzychody');
$row= $stmt->fetch();
$id_revenue_category=$row[0];

/*wstawiam wartoś›ci, z formularzy przychodów, do bazy danych tabela "revenues" */
$stmt = $pdo -> exec("INSERT INTO revenues VALUES('','{$_POST['revenue_enter_date']}','{$row[0]}','{$_POST['revenue_value']}','{$_POST['revenue_description']}')") or die('zły insert przychodów');

/*Wyciągam wielkość przychodu z tabeli categorii w celu dodania do niej kolejnej*/
$stmt = $pdo -> query("SELECT revenue_category_value FROM revenue_categories WHERE revenue_name='{$_POST['revenue_name']}'") or die('zły select kosztów');
$row=$stmt->fetch();
$revenue_category_value=$row[0]+$_POST['revenue_value'];

/*robię™ update wysokości przychody przy nazwach kosztów w tabeli categorie przychodów*/
$stmt= $pdo -> exec("UPDATE revenue_categories SET revenue_category_value='{$revenue_category_value}' WHERE id_revenue_category='{$id_revenue_category}'") or die('zły update przychodów ');


/*koszty*/

/*Wyciągam id kategorii koszty potrzebne do tabeli "costs*/
$stmt = $pdo -> query("SELECT id_cost_category FROM cost_categories WHERE cost_name='{$_POST['cost_name']}'") or die('zły select kosztów');
$row= $stmt->fetch();
$id_cost_category=$row[0];

/*wstawiam wartoś›ci, z formularzy przychodów, do bazy danych tabela "costs*/
$stmt = $pdo -> exec("INSERT INTO costs VALUES('','{$_POST['cost_enter_date']}','{$id_cost_category}','{$_POST['cost_value']}','{$_POST['cost_description']}')") or die('zł‚y insert kosztów');

/*Wyciągam wielkość‡ kosztu z tabeli categorii w celu dodania do niej kolejnej*/
$stmt = $pdo -> query("SELECT cost_category_value FROM cost_categories WHERE cost_name='{$_POST['cost_name']}'") or die('zły select kosztów');
$row=$stmt->fetch();
$cost_category_value=$row[0]+$_POST['cost_value'];

/*robię ™ update wysokości kosztów przy nazwach kosztów w tabeli categorie kosztów*/
$stmt= $pdo -> exec("UPDATE cost_categories SET cost_category_value='{$cost_category_value}' WHERE id_cost_category='{$id_cost_category}'") or die('zły update koszty');

echo 'dobrze';

include('../templates/footer.tpl');
?>


Efekt w html wygląda następująco:
Kod
<html>
<head>
<meta name="description" content="Warsztat programisty" />
<meta name="keywords" content="warsztat programisty,programowanie" />
<meta http-equiv="content-type" content="text/html; charset=utf-8" />
<link rel="Stylesheet" type="text/css" href="../templates/style.css" />
<title>Workshop</title>
</head>
<body>
    <div id="all">
        <div id="header"><h1>Panel sterowania</h1>
        </div>zły update przychodów

gdzie sam plik header kończy się na </div> zły update przychodów, to komunikat z die('zły update przychodów'); pochodzący z pierwszego zapytania update.

Gdy odwróciłem kolejność i dałem najpierw blok z kosztami, sytuacja była analogiczna.

Nie mam pojęcia już dlaczego źródło strony pokazuje błąd a sama strona i zapytania działają prawidłowo.
viking
$pdo = new PDO('mysql:host=localhost;dbname=cash', 'root', 'hasło') or die('zonk');

co to jest?

try {
$pdo = new PDO('mysql:host=localhost;dbname=cash', 'root', 'hasło');
} catch (PDOException $e) {
sprintf("zonk: %s", $e->getMessage);
}
Andrzej.W.
Cytat(viking @ 19.04.2013, 08:27:05 ) *
$pdo = new PDO('mysql:host=localhost;dbname=cash', 'root', 'hasło') or die('zonk');

co to jest?

try {
$pdo = new PDO('mysql:host=localhost;dbname=cash', 'root', 'hasło');
} catch (PDOException $e) {
sprintf("zonk: %s", $e->getMessage);
}

Dziękuję za odpowiedź.
To jest napisane roboczo. Uważasz że problem może leżeć w tym, iż nie opatrzyłem (jeśli dobrze rozumiem) wyjątkami ?
Dopiero popołudniem będę mógł to sprawdzić. Natomiast chciałem dodać try/catch dopiero w następnym kroku, uzupełniając kod. Po prostu badam krok poo kroku jak to działa i sądziłem, że w takiej formie, z poprawnymi danymi i połączeniem powinno było zadziałać.
Pozdrawiam.
Andrzej
viking
Kod należy pisać od początku tak, aby był bezpieczny i poprawny. Co według ciebie robi ta konstrukcja? Konstruktor PDO zwraca obiekt albo rzuca wyjątkiem. W związku z czym dostaniesz albo prawidłowy obiekt, albo Fatal error: Uncaught exception 'PDOException'...
Andrzej.W.
Cytat(viking @ 19.04.2013, 11:09:00 ) *
Kod należy pisać od początku tak, aby był bezpieczny i poprawny. Co według ciebie robi ta konstrukcja? Konstruktor PDO zwraca obiekt albo rzuca wyjątkiem. W związku z czym dostaniesz albo prawidłowy obiekt, albo Fatal error: Uncaught exception 'PDOException'...

Jasne rozumiem, weź proszę poprawkę, że analizuje krok po kroku działanie wszystkiego po kolei. Ale nie dziwi Cię fakt, że to wszystko zatrybiło, a jedyne co wskazuje na to, że coś jest nie tak, to źródło strony, do którego zajrzałem z przypadku, bo wszystko poszło jak trzeba.

Ale mam jeszcze jedno pytanie w związku z powyższym, jakbyś zechciał odpowiedzieć, czy każde zapytanie kierowane powinno się opatrzyć try/catch?.

Na wikibooks są tylko pojedyncze zapytania. Później chciałbym tą aplikacje przerobić na obiektowe, ale to toche jeszcze potrwa. Ja podstawy php miałem na kursie w tym roku i wszystkie operacje na bazie robiliśmy na mysql_connect itd, a parsowanie na if'ach. try/catch to dla mnie nowość, już co nie co zrozumiałem, ale widze jeszcze sporo zagadek, dlatego tak testuje.
Pozdrawiam.smile.gif
viking
W zależności od aplikacja cała może być objęta try/catch i np zawierać globalne logowanie błędów. Bloków try/catch może być dowolna ilość, mogą być zagnieżdzane a wyjątki ponownie rzucane (catch -> throw new Exception). Powinny być raczej logicznie grupowane o czym przekonasz się jak dojdziesz do transakcji (try->commit, catch->rollback).
Andrzej.W.
Uzupełniłem kod i tego błędu już nie ma.
Dodałem również polecenia/funkcje, które podpatrzyłem w wiki.

O ile znaczenie unset() i closeCursor(), o tyle nie jestem pewny, czy poprawnie ich użyłem. Prosiłbym o ogólną ocenę tego kodu, to w sumie pierwszy samodzielny z zastosowaniem elementów PDO.

Zależałoby mi na ocenie w kategoriach:

- W temacie dobrych praktyk, w zakresie przejrzystości.

- Czy takie rozłożenie try/catch jest logiczne?
(umyślnie nie wkleiłem tutaj bloku koszty, który widniał w poprzedniej wersji, gdyż jest zrobiony analogicznie.)

- I braków w kodzie. (Jeszcze nie przerobiłem np. bindowania, obecny if wrzuciłem nie wiedząc czemu służy, również nie wiele wiem o setAttribute, ale o nich sobie doczytam później. Natomiast nie wiem czego nie wiem i tu prośba o jakieś nakierowanie- wystarczą hasła. Filtrowanie za pomocą wyrażeń stałych zrobię sobie zaraz i z tym akurat problemu nie mam.

Kod
<?php
include('../templates/header.tpl');
    
    if($_SERVER['REQUEST_METHOD'] == 'POST'){
        try{
            $pdo = new PDO('mysql:host=localhost;dbname=cash', 'root', 'hasło');
            $pdo -> setAttribute(PDO::ATTR_ERRMODE, PDO::ERRMODE_EXCEPTION);

/*przychody*/

            $stmt = $pdo -> query("SELECT id_revenue_category FROM revenue_categories WHERE revenue_name='{$_POST['revenue_name']}'");
                
                $row= $stmt->fetch();
                $id_revenue_category=$row[0];
                $stmt -> closeCursor();
                unset($stmt);

            }catch (PDOException $e){
                sprintf("zonk: %s", $e->getMessage);
                                            }

        try{
            $stmt = $pdo -> exec("INSERT INTO revenues VALUES('','{$_POST['revenue_enter_date']}','{$row[0]}','{$_POST['revenue_value']}','{$_POST['revenue_description']}')");

                unset($stmt);

            }catch (PDOException $e){
                sprintf("zonk: %s", $e->getMessage);
                                            }


        try{
            $stmt = $pdo -> query("SELECT revenue_category_value FROM revenue_categories WHERE revenue_name='{$_POST['revenue_name']}'");

                $row=$stmt->fetch();
                $revenue_category_value=$row[0]+$_POST['revenue_value'];
                $stmt -> closeCursor();
                unset($stmt);
            
            }catch (PDOException $e){
                sprintf("zonk: %s", $e->getMessage);
                                            }
    

        try{
            $stmt= $pdo -> exec("UPDATE revenue_categories SET revenue_category_value='{$revenue_category_value}' WHERE id_revenue_category='{$id_revenue_category}'");

                unset($stmt);
            
            }catch (PDOException $e){
                sprintf("zonk: %s", $e->getMessage);
                                            }


    }else {include('cash_form_generator.php');}

include('../templates/footer.tpl');
?>

No i chciałem podziękować koledze, o nicku "viking", za pomoc, pkt."pomógł" już poszedł. smile.gif
Pozdrawiam.
Andrzej.
viking
Otwierasz sobie drogę na sql injection tym samym nie korzystasz wcale z jednych z podstawowych zalet pdo. Poczytaj o bindowaniu parametrów. Kiedyś pisałem o tym artykuł, jest w stopce link. Kod jest trochę bez sensu, same zapytania także wink.gif Zastanów się czy nie można ich połączyć.
Andrzej.W.
Kod
<?php
include('../templates/header.tpl');
error_reporting(E_ALL);
ini_set('display_errors', 'on');
if($_POST['revenue_name']==0){echo 'uzupełnij nazwę'; exit;}else{    
$row=explode(". ", $_POST['revenue_name']);}
        
        try{
        
    $pdo = new PDO('mysql:host=localhost;dbname=cash', 'root', 'hasło');
    $pdo -> setAttribute(PDO::ATTR_ERRMODE, PDO::ERRMODE_EXCEPTION);
                
$pdo->beginTransaction();
                
            
$sth = $pdo->prepare("INSERT INTO revenues VALUES(DEFAULT, ?, ?, ?, ?)");
                
                
                
$sth->bindParam(':revenue_enter_date', $_POST['revenue_enter_date'], PDO::PARAM_STR);
$sth->bindParam(':id_revenue_category', $row[0], PDO::PARAM_STR);
$sth->bindParam(':revenue_value', $_POST['revenue_value'], PDO::PARAM_STR);
$sth->bindParam(':revenue_enter_date', $_POST['revenue_description'], PDO::PARAM_STR);
                
sth->execute(array($_POST['revenue_enter_date'],$row[0],$_POST['revenue_value'],$_POST['revenue_description']));
                
                $stmt = $pdo->prepare("UPDATE revenue_categories SET revenue_category_value=revenue_category_value+{$_POST['revenue_value']} WHERE id_revenue_category={$row[0]}");
                $stmt->bindParam(":revenue_value", $_POST['revenue_value']);
                $stmt->execute();
                
    $pdo->commit();        
     }
        catch(PDOException $e)
        {
                    $pdo->rollBack();
                echo 'Wystapil blad biblioteki PDO: ' . $e->getMessage();
        }

    

include('../templates/footer.tpl');
?>


Czy zatem teraz moje wypociny spełniają kryteria bezpieczeństwa i poprawności, rozumiem każdą linijke tego kodu, aczkolwiek pewności nie mam czy prawidłowo. Fakt, że patrząc na niego, tamte wydają mi sie straszną kaszaną.

Mam parę pytań:

1. Czy stosując taki sposób współpracy z bazą danych, trzeba/warto przepuszczać dane przez wyrażenia stałe?
2. Czy jest sens bindować dane pochodzące z checkboxów, czy też menu rozwijalnego?
3. Czy stosując formułę "required" w formularzach, sprawdzać dodatkowo skryptem, czy są wypełnione?
4. Czy tak jak w tym kodzie powtórne bindowanie tego samego parametru, którego użyłem w zapytaniu UPDATE jest uzasadnione?

Zatem zapytuję po raz wtóry, czego jeszcze nie wiem, w temacie bezpiecznych i prawidłowych połączeń z bazą? smile.gif
Pozdrawiam.
Andrzej.
viking
Wszystko co pochodzi od użytkownika musi być zawsze bezwzględnie filtrowane. W związku z tym co robi w UPDATE wstawiony POST? Pomieszałeś też bindowanie. :xxx odnosi się do zdefiniowanej nazwy :xxx w zapytaniu. Execute przypina po kolei do placeholderów w zapytaniu. Albo jedno, albo drugie. required w formularzu jest tylko dodatkiem, mogę to usunąć, w dodatku mogę wysłać cały formularz nawet przez nie twoja stronę.
Andrzej.W.
Kod
<?php
include('../templates/header.tpl');
error_reporting(E_ALL);
ini_set('display_errors', 'on');
if($_POST['revenue_name']==0){echo 'uzupełnij nazwę'; exit;}else{    
$row=explode(". ", $_POST['revenue_name']);}
        
        try{
        
                $pdo = new PDO('mysql:host=localhost;dbname=cash', 'root', 'hasło');
                $pdo -> setAttribute(PDO::ATTR_ERRMODE, PDO::ERRMODE_EXCEPTION);
                
$pdo->beginTransaction();
                
            
                $sth = $pdo->prepare("INSERT INTO revenues VALUES(DEFAULT, ?, ?, ?, ?)");
                
                
                
                $sth->bindParam(1, $_POST['revenue_enter_date'], PDO::PARAM_STR);
                $sth->bindParam(2, $row[0], PDO::PARAM_INT);
                $sth->bindParam(3, $_POST['revenue_value'], PDO::PARAM_INT);
                $sth->bindParam(4, $_POST['revenue_description'], PDO::PARAM_STR);
                
                $sth->execute(array($_POST['revenue_enter_date'],$row[0],$_POST['revenue_value'],$_POST['revenue_description']));
                
                $stmt = $pdo->prepare("UPDATE revenue_categories SET revenue_category_value=revenue_category_value+? WHERE id_revenue_category=?");
                $stmt->bindParam(1, $_POST['revenue_value'], PDO::PARAM_STR);
                $stmt->bindParam(2, $row[0], PDO::PARAM_INT);
                
                $stmt->execute(array($_POST['revenue_value'],$row[0]));
                
    $pdo->commit();        
     }
        catch(PDOException $e)
        {
                    $pdo->rollBack();
                echo 'Wystapil blad biblioteki PDO: ' . $e->getMessage();
        }

    

include('../templates/footer.tpl');
?>

Jeszcze jakieś uwagi? smile.gif
To jest wersja lo-fi głównej zawartości. Aby zobaczyć pełną wersję z większą zawartością, obrazkami i formatowaniem proszę kliknij tutaj.
Invision Power Board © 2001-2025 Invision Power Services, Inc.