Pomoc - Szukaj - Użytkownicy - Kalendarz
Pełna wersja: Zaprojektowanie klasy użytkownika - jak to wygląda od węwnątrz?
Forum PHP.pl > Forum > PHP > Object-oriented programming
kubek3898
Witam, zaczynam dopiero zabawę z programowaniem OOP w PHP i zastanawia mnie jak ma wyglądać klasa użytkownika (logowanie, rejestracja itp.). To co napisałem do tej pory wydaje mi się zagmatwane i napisane mało profesjonalnie, a chciałbym by klasa była "ładnie" napisana. Największy problem mam z wyobrażeniem sobie w jaki sposób ma działać np. logowanie. Czy przesłane argumenty do tej metody mam porównywać wysyłając zapytanie do bazy danych, czy może wystarczą dane składowe tej klasy, które przypisuję w momencie rejestracji. Również zastanawia mnie jak i gdzie ma działać sesja? Wydaje mi się, że klasa równie dobrze działała by bez tych danych składowych takich jak login, czy adres E - Mail, jednak wtedy to straciło by sens. Może mnie ktoś naprowadzić jak taki kod powinien wyglądać?

To co dotychczas nabazgrałem:

  1. <?php
  2.  
  3. require_once 'config.php';
  4. require_once 'class.mysql.php';
  5.  
  6. class User
  7. {
  8. private $id;
  9. private $username;
  10. private $password;
  11. private $email;
  12.  
  13. private $db;
  14.  
  15. public function __construct($db)
  16. {
  17. $this->db = $db;
  18.  
  19. }
  20.  
  21. public function __destruct()
  22. {
  23. $this->db = null;
  24.  
  25. }
  26.  
  27. public function register($username, $password, $email)
  28. {
  29. if(!filter_var($email, FILTER_VALIDATE_EMAIL))
  30. {
  31. throw new Exception('Email is not valid!', 1);
  32. }
  33. else if(strlen($password) < 4 || strlen($password) > 20)
  34. {
  35. throw new Exception('Password is not valid', 2);
  36. }
  37. else if(strlen($username) < 4 || strlen($username) > 20)
  38. {
  39. throw new Exception('Username is not valid!', 3);
  40. }
  41.  
  42. // Checking for exists user
  43. $checkExistsUser = 'SELECT `id` FROM `' . USERS_TABLE_NAME . '` WHERE `username`=:username;';
  44. $sth = $this->db->prepare($checkExistsUser);
  45. $sth->bindValue(':username', $username, PDO::PARAM_STR);
  46. $sth->execute();
  47.  
  48. if($sth->rowCount() > 0)
  49. {
  50. throw new Exception('Someone have got account with this username!', 5);
  51. }
  52. else
  53. {
  54. $password = hash('sha256', $password);
  55.  
  56. // Insert new user to database
  57. $insertNewUser = 'INSERT INTO `' . USERS_TABLE_NAME . '`
  58. (`id`, `username`, `password`, `email`) VALUES
  59. (NULL, :username, :password, :email);';
  60. $sth = $this->db->prepare($insertNewUser);
  61. $sth->bindValue(':username', $username, PDO::PARAM_STR);
  62. $sth->bindValue(':password', $password, PDO::PARAM_STR);
  63. $sth->bindValue(':email', $email, PDO::PARAM_STR);
  64. $checkSuccess = $sth->execute();
  65.  
  66. if($checkSuccess > 0)
  67. {
  68. throw new Exception('Register successfully!', 6);
  69. $this->id = $_SESSION['id'] = $this->db->lastInsertId();
  70. $this->username = $_SESSION['username'] = $username;
  71. $this->password = $password;
  72. $this->email = $_SESSION['email'] = $email;
  73. }
  74. else
  75. {
  76. throw new Exception('Register failed!', 7);
  77. }
  78. }
  79. }
  80.  
  81. // Najbardziej interesuje mnie jak wyglądać ma ta funkcja...
  82. public function login($username, $password)
  83. {
  84. if(strlen($password) < 4 || strlen($password) > 20)
  85. {
  86. throw new Exception('Password is not valid', 2);
  87. }
  88. else if(strlen($username) < 4 || strlen($username) > 20)
  89. {
  90. throw new Exception('Username is not valid!', 3);
  91. }
  92.  
  93. if($this->username == $username && $this->password == $password)
  94. {
  95. throw new Exception('Login successfully!', 8);
  96. }
  97. else
  98. {
  99. throw new Exception('Login failed!', 9);
  100. }
  101. }
  102. }
  103.  
  104. ?>


I jeszcze jedno pytanie. Czy rzucanie wyjątków mogę wykorzystwać również do sytuacji wcale nie wyjątkowych? Takie coś działa, lecz chciałem się dowiedzieć czy nie jest to mało profesjonalne.
PrinceOfPersia
Wyjątki są do obsługi błędów. Działają tak, że przerywane jest działanie programu i skrypt przeskakuje do miejsca w kodzie, które będzie mogło obsłużyć ten wyjątek. Jeśli takiego miejsca nie ma, to intepreter wypisze ten błąd na ekranie.

Cytat
throw new Exception('Register failed!', 7);

to jest okej. Ale to już nie bardzo:

Cytat
throw new Exception('Login successfully!', 8);

jeśli Login successfully, to po co wyjątek? Nie wystarczy return true albo coś w tym rodzaju?

No i te wyjątki powinieneś jakoś łapać w funkcji nadrzędnej (w klauzuli try...catch), bo inaczej to bez sensu. Na przykład:
Kod
try {
  $user->login();



  // jesli zostanie rzucony wyjatek, nastepna linijka w ogole nie bedzie wykonana!
  // dlatego mozemy założyć, że jeśli dalej się kod wykonuje, to logowanie przebiegło bez błędu
  // i możemy zmienic hasło
  // jesli natomiast cos w funkcji $user->login padło, poniższa linijka się nie wykona,
   // i skrypt przeskoczy do bloku catch

  $user->changePassword('kotek123'); // przykladowa funkcja

} catch (Exception $e) {
    
    redirectToTheHomePage('wystapil blad przy logowaniu'); // wymyślona funkcja
}
amii
Tak szczerze mówiąc to ten kod z regułami wzorcowego OOP ma nie wiele wspólnego. To na co w powinnieś zwrócić uwagę:
1. Każda klasa wykonuje ściśle określone zadanie
2. MVC czyli trójwarstowy podział na model, widok i kontroler
3. Zainterewsuj się czymś takim jak service container i dependency injection - ogólnie to fajnie w symfony2 jest zrobione
http://symfony.com/doc/current/book/service_container.html
http://www.youtube.com/watch?v=DcNtg4_i-2w

To tak tyle na początek smile.gif
kubek3898
Cytat(PrinceOfPersia @ 28.12.2013, 22:55:41 ) *
Wyjątki są do obsługi błędów. Działają tak, że przerywane jest działanie programu i skrypt przeskakuje do miejsca w kodzie, które będzie mogło obsłużyć ten wyjątek. Jeśli takiego miejsca nie ma, to intepreter wypisze ten błąd na ekranie.


to jest okej. Ale to już nie bardzo:


jeśli Login successfully, to po co wyjątek? Nie wystarczy return true albo coś w tym rodzaju?

No i te wyjątki powinieneś jakoś łapać w funkcji nadrzędnej (w klauzuli try...catch), bo inaczej to bez sensu. Na przykład:
Kod
try {
  $user->login();



  // jesli zostanie rzucony wyjatek, nastepna linijka w ogole nie bedzie wykonana!
  // dlatego mozemy założyć, że jeśli dalej się kod wykonuje, to logowanie przebiegło bez błędu
  // i możemy zmienic hasło
  // jesli natomiast cos w funkcji $user->login padło, poniższa linijka się nie wykona,
   // i skrypt przeskoczy do bloku catch

  $user->changePassword('kotek123'); // przykladowa funkcja

} catch (Exception $e) {
    
    redirectToTheHomePage('wystapil blad przy logowaniu'); // wymyślona funkcja
}


Co do tej obsługi błędów - wiem to wszystko. Blok try i catch używam nie w samej klasie, a w pliku gdzie ta metodę z klasy wywołuje (dajmy na to index.php). Ogólnie ogarniam wyjątki, wiem do czego służą i jak się obsługuję, ale w książce Pasja C++, J. Grębosza w którymś z ostatnich rozdziałów autor wspomina, że wyjątki nie zawszę służą do spraw wyjątkowych. Można nimi właśnie sygnalizować takie rzeczy, pomyślne (w książce był akurat przykład zagnieżdżonych pętel, z której rzucano wyjątek gdy został znaleziony skarb w symulowanej grze). Tutaj użyłem tego zamiast return z dwóch powodów:

- wygląda to przejrzyściej gdy wszędzie używam instrukcji throw, a nie na przemian
- chciałem, by w przypadku błędu czy sukcesu funkcja zwróciła kod, oraz dodatkowo wiadomość


Dziękuje bardzo za odpowiedzi oraz linki użytkownika @up.
PrinceOfPersia
Cytat
- chciałem, by w przypadku błędu czy sukcesu funkcja zwróciła kod, oraz dodatkowo wiadomość


a co za problem zwrócić tablicę? wink.gif
  1. return array('code'=>8, 'info'=>'wrong password');
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.