Witaj Gościu! ( Zaloguj | Rejestruj )

Forum PHP.pl

> PDO w akcji
PawelC
post 18.07.2011, 18:33:03
Post #1





Grupa: Zarejestrowani
Postów: 1 173
Pomógł: 121
Dołączył: 24.09.2007
Skąd: Toruń

Ostrzeżenie: (0%)
-----


Witam smile.gif
Tworzę sobie klasę do zarządzania użytkownikiem, czyli dodanie, kasowanie, wyświetlenia loginu i póki co hasła, chciałem Was jako bardziej doświadczonych speców, zapytać czy wszystko jest dobrze w kodzie. Proszę również o ocenę podziału, zarządzania użytkownikiem na 2 klasy, z których każda robi co innego.

UserManager.php
  1. <?php
  2. class UserManager{
  3.  
  4. //Database connection
  5. public function __construct()
  6. {
  7. try
  8. {
  9. $this->db = new PDO('mysql: host=localhost; dbname=test', 'root','');
  10. }
  11. catch(PDOException $e)
  12. {
  13. throw new Exception($e->getMessage());
  14. }
  15. }
  16.  
  17. //Create new user
  18. public function create($user, $pass)
  19. {
  20. $result=$this->db->prepare("INSERT INTO users VALUES('',:user,:pass)");
  21. $result->bindParam(':user',$user, PDO::PARAM_STR);
  22. $result->bindParam(':pass',$pass, PDO::PARAM_STR);
  23. if(!$result->execute()){
  24. throw new Exception('Konto nie zostało utworzone!');
  25. }
  26. }
  27.  
  28. //Delete user
  29. public function delete($id)
  30. {
  31. $result=$this->db->prepare("DELETE FROM users WHERE id=:id LIMIT 1");
  32. $result->bindParam(':id',$id, PDO::PARAM_INT);
  33. if(!$result->execute()){
  34. throw new Exception("Wystąpił bląd podczas kasowania użytkownika!");
  35. }
  36. }
  37. }
  38. ?>


User.php

  1. <?php
  2. class User{
  3.  
  4. //Database connection
  5. public function __construct()
  6. {
  7. try
  8. {
  9. $this->db = new PDO('mysql: host=localhost; dbname=test', 'root','');
  10. }
  11. catch(PDOException $e)
  12. {
  13. throw new Exception($e->getMessage());
  14. }
  15. }
  16.  
  17. //Select username
  18. public function getUsername($id)
  19. {
  20. $result=$this->db->prepare("SELECT user FROM users WHERE id=:id limit 1");
  21. $result->bindParam(':id',$id, PDO::PARAM_INT);
  22. if(!$result->execute())
  23. {
  24. throw new Exception("Wystąpił bląd podczas pobierania użytkownika!");
  25. }else{
  26. $wynik=$result->fetch(PDO::FETCH_OBJ);
  27. return $wynik->user;
  28. }
  29. }
  30.  
  31. //Select user password
  32. public function getPassword($id)
  33. {
  34. $result=$this->db->prepare("SELECT pass FROM users WHERE id=:id limit 1");
  35. $result->bindParam(':id',$id, PDO::PARAM_INT);
  36. if(!$result->execute())
  37. {
  38. throw new Exception("Wystąpił bląd podczas pobierania użytkownika!");
  39. }else{
  40. $wynik=$result->fetch(PDO::FETCH_OBJ);
  41. return $wynik->pass;
  42. }
  43. }
  44. }
  45. ?>


Ten post edytował ExPlOiT 18.07.2011, 19:00:19
Go to the top of the page
+Quote Post
 
Start new topic
Odpowiedzi (1 - 18)
yevaud
post 18.07.2011, 18:38:08
Post #2





Grupa: Zarejestrowani
Postów: 471
Pomógł: 89
Dołączył: 29.07.2008
Skąd: Warszawa

Ostrzeżenie: (0%)
-----


nie rozumiem dlaczego kazdy "user" samodzielnie laczy sie z baza i ma prywatne polaczenie
oprocz tego nie rozumiem czym sie rozni "manager" od "usera", skoro w obu przypadkach traktujesz te klasy tylko jako interfejs do laczenia sie z baza, a nie np. klasy dla samodzielnych obiektow konkretnych uzytkownikow

Ten post edytował yevaud 18.07.2011, 18:40:07
Go to the top of the page
+Quote Post
PawelC
post 18.07.2011, 18:41:20
Post #3





Grupa: Zarejestrowani
Postów: 1 173
Pomógł: 121
Dołączył: 24.09.2007
Skąd: Toruń

Ostrzeżenie: (0%)
-----


Z tą bazą akurat tymczasowo, chodzi mi o resztę kodu wink.gif

Co do podziału User i UserManager, sugerowałem się wypowiedzą Crozin-a, z tego postu: http://forum.php.pl/index.php?s=&showt...st&p=880097 chyba, że go źle zrozumiałem.

Ten post edytował ExPlOiT 18.07.2011, 18:43:54
Go to the top of the page
+Quote Post
erix
post 18.07.2011, 18:43:15
Post #4





Grupa: Moderatorzy
Postów: 15 467
Pomógł: 1451
Dołączył: 25.04.2005
Skąd: Szczebrzeszyn/Rzeszów




Ty hasło trzymasz plaintekstem...?


--------------------

ZCE :: Pisząc PW załączaj LINK DO TEMATU i TYLKO w sprawach moderacji :: jakiś błąd - a TREŚĆ BŁĘDU? :: nie ponaglaj z odpowiedzią via PW!
Go to the top of the page
+Quote Post
PawelC
post 18.07.2011, 18:45:26
Post #5





Grupa: Zarejestrowani
Postów: 1 173
Pomógł: 121
Dołączył: 24.09.2007
Skąd: Toruń

Ostrzeżenie: (0%)
-----


md5 smile.gif na główkę nie upadłem, żeby nie kodować go. Tyle, że kodowanie hasła jest poza klasą, i do klasy trafia zakodowane md5
Go to the top of the page
+Quote Post
Spawnm
post 18.07.2011, 18:53:14
Post #6





Grupa: Moderatorzy
Postów: 4 069
Pomógł: 497
Dołączył: 11.05.2007
Skąd: Warszawa




raz dajesz echo raz exception przy try...
new pdo wywal po za klasy.
Go to the top of the page
+Quote Post
PawelC
post 18.07.2011, 19:04:02
Post #7





Grupa: Zarejestrowani
Postów: 1 173
Pomógł: 121
Dołączył: 24.09.2007
Skąd: Toruń

Ostrzeżenie: (0%)
-----


Spawnm echo poprawione smile.gif I teraz pytanie do Was, lepiej jest robić taki podział jak widać u mnie, czy tworzyć jedną klasę, która utworzy, skasuje, wyświetli dane usera itp?

Ten post edytował ExPlOiT 18.07.2011, 19:05:25
Go to the top of the page
+Quote Post
Fifi209
post 18.07.2011, 19:05:11
Post #8





Grupa: Zarejestrowani
Postów: 4 655
Pomógł: 556
Dołączył: 17.03.2009
Skąd: Katowice

Ostrzeżenie: (0%)
-----


Jak dla mnie obie klasy powinny przyjmować jako parametr uchwyt do pdo - to raz.

Dwa klasa user - powinna w konstruktorze przyjmować id użytkownika jak dla mnie - przynajmniej wygląda, że byłoby lepiej.
getUsername - w obecnym przypadku powinno być raczej getUsernameByID


--------------------
Zainteresowania: C#, PHP, JS, SQL, AJAX, XML, C dla AVR
Chętnie pomogę, lecz zanim napiszesz: Wujek Google , Manual PHP
Go to the top of the page
+Quote Post
PawelC
post 18.07.2011, 19:52:40
Post #9





Grupa: Zarejestrowani
Postów: 1 173
Pomógł: 121
Dołączył: 24.09.2007
Skąd: Toruń

Ostrzeżenie: (0%)
-----


Wymodziłem coś takiego:
  1. <?php
  2. class User{
  3. private $_db;
  4. //Database connection
  5. public function __construct(DB $_db)
  6. {
  7. $this->db=$_db;
  8. }
  9. //Ciąg dalszy klasy User

Klasa DB
  1. <?php
  2.  
  3. class DB
  4. {
  5. public function __construct()
  6. {
  7. try
  8. {
  9. $this->baza = new PDO('mysql: host=localhost; dbname=test', 'root','');
  10. }
  11. catch(PDOException $e)
  12. {
  13. throw new Exception($e->getMessage());
  14. }
  15. }
  16.  
  17. public function prepare($query)
  18. {
  19. return $result=$this->baza->prepare($query);
  20. }
  21. }
  22.  
  23. ?>


I działa dobrze smile.gif

Ten post edytował ExPlOiT 18.07.2011, 20:16:50
Go to the top of the page
+Quote Post
Spawnm
post 18.07.2011, 20:08:59
Post #10





Grupa: Moderatorzy
Postów: 4 069
Pomógł: 497
Dołączył: 11.05.2007
Skąd: Warszawa




Zainteresuj się frameworkami. Taka dobra rada.
Jak dajesz private/protected to rozpoczynaj nazwę od _ czyli private $_db;
Poczytaj o bindColumn() w pdo.
Jeśli chodzi o pytanie czy dzielić na kilka klas czy posiadać jedną której zadaniem będzie zarządzanie userami,
to już sam musisz zdecydować jak ci wygodniej.
Go to the top of the page
+Quote Post
PawelC
post 18.07.2011, 20:16:24
Post #11





Grupa: Zarejestrowani
Postów: 1 173
Pomógł: 121
Dołączył: 24.09.2007
Skąd: Toruń

Ostrzeżenie: (0%)
-----


Dziękuję za rady smile.gif Co do frameworka, od 2 miesięcy używam ZF, ale chcę poznać OOP w lepszym stopniu niż podstawowy. Czasami tworzę jakiś bardzo mały projekt, gdzie framework nie jest kompletnie potrzebny, dlatego wolę mieć gotowy zestaw klas.

Wiem, że znając bardzo dobrze danego frameworka idzie bardzo szybko napisać aplikację, bo sam się o tym przekonałem.

//Kod poprawiłem
Go to the top of the page
+Quote Post
fullrespect
post 16.10.2012, 21:55:23
Post #12





Grupa: Zarejestrowani
Postów: 17
Pomógł: 0
Dołączył: 24.05.2012

Ostrzeżenie: (10%)
X----


Witam,
troche odkurzę temat...

Przepraszam ze znow będzie pytanie "czy dobrze robie" ale jestem na etapie nauki OOP w PHP.

Moim zamiarem bylo stworzenie klasy która bedzie miala za zadanie skrócenie sobie pisania bloku "try {} catch {}".

Nie wiem czy to co wymodziłem w ogole się nadaje do zastosowania (ogólnie to mi działa tak jak założyłem) ale chcialbym sie dowiedzieć czy nie zrobiłem jakichś rażących błędów.

  1. class DbManager extends PDO
  2. {
  3. private $_dbh;
  4. private $_result;
  5.  
  6.  
  7. public function __construct()
  8. {
  9. try {
  10. $this->_dbh = new PDO('mysql:dbname=rcs_wrs_dev; host=127.0.0.1', 'rcs_tomek', 'zmielonamarchewka',
  11. array(PDO::MYSQL_ATTR_INIT_COMMAND => "SET NAMES utf8"));
  12. $this->_dbh->setAttribute(PDO::ATTR_ERRMODE, PDO::ERRMODE_EXCEPTION);
  13. } catch( PDOException $e ) {
  14. echo( $e->getMessage() );
  15. }
  16. }
  17.  
  18.  
  19. public function fetch($query) {
  20. try {
  21. if ( $_result = $this->_dbh->query($query)->fetch() ) {
  22. return $_result;
  23. } else {
  24. return 0;
  25. }
  26. }
  27. catch (PDOException $e) {
  28. echo( $e->getMessage() );
  29. }
  30. }
  31.  
  32.  
  33. public function fetchAll($query) {
  34. try {
  35. if ( $_result = $this->_dbh->query($query)->fetchAll() ) {
  36. return $_result;
  37. } else {
  38. return 0;
  39. }
  40. } catch (PDOException $e) {
  41. echo( $e->getMessage() );
  42. }
  43. }
  44. }


a używam tego tak:

  1. $wiersz = $db->fetch("SELECT Pressure FROM tasks WHERE task_id=94");
  2.  
  3.  
  4. var_dump($wiersz);
  5.  
  6. // array(2) { ["Pressure"]=> string(4) "1029" [0]=> string(4) "1029" }
  7.  


I wszystko wygląda jakby chciało działać smile.gif a w razie błędu/literówki dostanę komunikat.

Dzieki za wszystkie uwagi.

Ten post edytował fullrespect 16.10.2012, 22:43:05
Go to the top of the page
+Quote Post
-=Peter=-
post 16.10.2012, 22:26:20
Post #13





Grupa: Zarejestrowani
Postów: 304
Pomógł: 51
Dołączył: 4.02.2005
Skąd: Kraków

Ostrzeżenie: (0%)
-----


Aby uzyskać podobny efekt wystarczy nie wywoływać poniższej linijki w konstruktorze i usunąć wszystkie instrukcje try catch.

  1. $this->dbh->setAttribute(PDO::ATTR_ERRMODE, PDO::ERRMODE_EXCEPTION);


Ten kod, który podałeś jest idiotyczny, wyrzuć go - nie żartuję. Jeśli się uczysz OOP to musisz się nauczyć stosować wyjątki i musisz zrozumieć ich przewagę nad tradycyjną obsługą błędów, która jest stosowana w całej bibliotece standardowej php ze względu na zaszłości historyczne.


--------------------
Go to the top of the page
+Quote Post
fullrespect
post 17.10.2012, 11:55:35
Post #14





Grupa: Zarejestrowani
Postów: 17
Pomógł: 0
Dołączył: 24.05.2012

Ostrzeżenie: (10%)
X----


OK, rozumiem że powinno używać się wyjątków (z tego co się orientuje to PDO ma swoje wyjątki i dlatego ich używam).
Poczytałem http://pl.wikibooks.org/wiki/PHP/Wyj%C4%85tki i tam piszą tak:
Cytat
Obsługę wyjątków posiada jedynie kilka najnowszych, obiektowych modułów:

Standard PHP Library
Biblioteka PHAR
Biblioteka PDO


Nie rozumiem czemu mam się pozbyć bloku try, catch ? Nawet na php.net jest to stosowane: http://www.php.net/manual/pl/language.exceptions.php


Albo coś pominąłem albo nie mam zielonego pojęcia co ja robię tu smile.gif
Go to the top of the page
+Quote Post
-=Peter=-
post 17.10.2012, 20:51:33
Post #15





Grupa: Zarejestrowani
Postów: 304
Pomógł: 51
Dołączył: 4.02.2005
Skąd: Kraków

Ostrzeżenie: (0%)
-----


Usuwając bloki try catch miałem na myśli metody klasy DbManager. Bloki try catch powinny być w kodzie klienta obiektu DbManager. Twój kod jest bardzo zły bo nie mamy kontroli nad tym czy wystąpił błąd. Wywołując poszczególne metody nie wiemy czy nie spowodowała ona błędu. Przykładowo:

  1. $db = new DbManager();
  2. //nie wiemy czy zostało nawiązane poprawne połączenie z bazą danych, czy nie
  3.  
  4. $data = $db->fetch(...);
  5.  
  6. //nie wiemy czy wystąpił błąd, nie wiemy nawet czy $db ma poprawny stan (połączenie z bazą się powiodło)
  7. //rób coś z $data
  8.  
  9. $data = $db->fetchAll(...);
  10.  
  11. //nie wiemy czy wystąpił błąd...
  12. //rób coś z $data


Można poprawić ten kod poprzez zwracanie jakieś określonej wartości w przypadku błędu, zazwyczaj jest to wartość false lub -1 (czasy C oraz php przed pojawieniem się wyjątków wink.gif)

  1. //metody DbManager
  2.  
  3. public function fetch($query) {
  4. if(błąd) {
  5. return false;
  6. } else {
  7. return wynik zapytania;
  8. }
  9. }
  10.  
  11. public function fetchAll($query) {
  12. if(błąd) {
  13. return false;
  14. } else {
  15. return wynik zapytania;
  16. }
  17. }
  18.  
  19. //kod klienta
  20. $db = new DbManager();
  21. //nadal nie wiemy czy połączenie się powiodło
  22.  
  23. $data = $db->fetch(...);
  24.  
  25. if($data === false) {
  26. //obsługa błędu
  27. } else {
  28. //rób coś z danymi
  29. }
  30.  
  31. $data = $db->fetchAll(...);
  32.  
  33. if($data === false) {
  34. //obsługa błędu
  35. } else {
  36. //rób coś z danymi
  37. }


To rozwiązanie już jest odrobinę lepsze, ale minusem jest to że kod obsługi błędów jest wymieszany z kodem prawidłowego przebieg programu, błąd obsługiwać trzeba natychmiast po wywołaniu metody oraz jest pełno instrukcji warunkowych i powtórzeń kodu obsługi błędów.

Ostatnie rozwiązanie to wyjątki, jeśli wystąpił błąd to rzucaj wyjątkiem.

  1. //przechwytuje wyjątki w kliencie obiektu DbManager, a nie w samej klasie DbManager
  2. try {
  3. //w tym bloku nie zawracamy sobie dupy błędamy, bo zakładam że każda metoda wyrzuci wyjątek jeśli wystąpi błąd
  4.  
  5. $db = new DbManager();
  6. $data = $db->fetch(...);
  7. //rób coś z $data
  8. $data = $db->fetchAll(...);
  9. //rób coś z $data
  10. } catch (Exception $e){
  11. //obsługa błędów. Tutaj wskoczymy jeśli którakolwiek z metod wyrzuci wyjątek
  12. }


--------------------
Go to the top of the page
+Quote Post
!*!
post 17.10.2012, 21:00:59
Post #16





Grupa: Zarejestrowani
Postów: 4 298
Pomógł: 447
Dołączył: 16.11.2006

Ostrzeżenie: (0%)
-----


Tylko po co te nakładki? Tylko po to, aby kod był "krótki" ? I dane połączenia tworzą się same w konstruktorze?


--------------------
Nie udzielam pomocy poprzez PW i nie mam GG.
Niektóre języki programowania, na przykład C# są znane z niezwykłej przenośności (kompatybilność ze wszystkimi wersjami Visty jest wiele warta).
Go to the top of the page
+Quote Post
fullrespect
post 20.10.2012, 01:12:55
Post #17





Grupa: Zarejestrowani
Postów: 17
Pomógł: 0
Dołączył: 24.05.2012

Ostrzeżenie: (10%)
X----


@-=Peter=-
Dzieki za wskazówki i pięknie przedstawiony kod.

Ale wychodzi na to ze now musze klepac try {} catch {} na kazdym kroku...
A moze polecice jakis artykól o wyjątkach i ich traktowaniu ?

Ten post edytował fullrespect 20.10.2012, 01:13:19
Go to the top of the page
+Quote Post
!*!
post 20.10.2012, 13:09:38
Post #18





Grupa: Zarejestrowani
Postów: 4 298
Pomógł: 447
Dołączył: 16.11.2006

Ostrzeżenie: (0%)
-----


Cytat(fullrespect @ 20.10.2012, 02:12:55 ) *
A moze polecice jakis artykól o wyjątkach i ich traktowaniu ?

http://pl.wikibooks.org/wiki/PHP/Wyjątki


--------------------
Nie udzielam pomocy poprzez PW i nie mam GG.
Niektóre języki programowania, na przykład C# są znane z niezwykłej przenośności (kompatybilność ze wszystkimi wersjami Visty jest wiele warta).
Go to the top of the page
+Quote Post
pamil
post 20.10.2012, 13:38:31
Post #19





Grupa: Zarejestrowani
Postów: 97
Pomógł: 15
Dołączył: 12.08.2012
Skąd: Zabrze

Ostrzeżenie: (10%)
X----


Cytat(Spawnm @ 18.07.2011, 21:08:59 ) *
Jak dajesz private/protected to rozpoczynaj nazwę od _ czyli private $_db;

To naleciałość z PHP4, aby oznaczyć daną właściwość jako prywatną, teraz ze względu na modyfikatory dostępu to nie ma sensu.
Go to the top of the page
+Quote Post

Reply to this topicStart new topic
1 Użytkowników czyta ten temat (1 Gości i 0 Anonimowych użytkowników)
0 Zarejestrowanych:

 



RSS Wersja Lo-Fi Aktualny czas: 14.08.2025 - 07:03