![]() |
![]() |
-Andrzej.W.- |
![]()
Post
#1
|
Goście ![]() |
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. Ten post edytował Andrzej.W. 19.04.2013, 07:22:55 |
|
|
![]() |
![]()
Post
#2
|
|
Grupa: Zarejestrowani Postów: 6 380 Pomógł: 1116 Dołączył: 30.08.2006 Ostrzeżenie: (0%) ![]() ![]() |
$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.- |
![]()
Post
#3
|
Goście ![]() |
$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 Ten post edytował Andrzej.W. 19.04.2013, 09:14:13 |
|
|
![]()
Post
#4
|
|
Grupa: Zarejestrowani Postów: 6 380 Pomógł: 1116 Dołączył: 30.08.2006 Ostrzeżenie: (0%) ![]() ![]() |
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.- |
![]()
Post
#5
|
Goście ![]() |
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. ![]() |
|
|
![]()
Post
#6
|
|
Grupa: Zarejestrowani Postów: 6 380 Pomógł: 1116 Dołączył: 30.08.2006 Ostrzeżenie: (0%) ![]() ![]() |
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.- |
![]()
Post
#7
|
Goście ![]() |
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ł. ![]() Pozdrawiam. Andrzej. Ten post edytował Andrzej.W. 19.04.2013, 18:47:54 |
|
|
![]()
Post
#8
|
|
Grupa: Zarejestrowani Postów: 6 380 Pomógł: 1116 Dołączył: 30.08.2006 Ostrzeżenie: (0%) ![]() ![]() |
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
![]() -------------------- |
|
|
-Andrzej.W.- |
![]()
Post
#9
|
Goście ![]() |
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ą? ![]() Pozdrawiam. Andrzej. Ten post edytował Andrzej.W. 20.04.2013, 16:16:27 |
|
|
![]()
Post
#10
|
|
Grupa: Zarejestrowani Postów: 6 380 Pomógł: 1116 Dołączył: 30.08.2006 Ostrzeżenie: (0%) ![]() ![]() |
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.- |
![]()
Post
#11
|
Goście ![]() |
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? ![]() Ten post edytował Andrzej.W. 20.04.2013, 18:33:54 |
|
|
![]() ![]() |
![]() |
Aktualny czas: 19.08.2025 - 16:30 |