Pomoc - Szukaj - Użytkownicy - Kalendarz
Pełna wersja: [OOP] problemy początkującego - rejestracja
Forum PHP.pl > Forum > PHP
szczypior
Witam

Postanowiłem spróbować swoich sił w OOP, na przykładzie skryptu rejestracji użytkowników. Napisałem coś takiego i o dziwo działa winksmiley.jpg Gdy dane są poprawne dodaje użytkownika, gdy nie to nie dodaje, ale za to również nie wyświetla komunikatu. Moja prośba do Was, doświadczonych w temacie osób, to zobaczenie czy ten kod jest napisany poprawnie (zgodnie ze sztuką), co można w nim ulepszyć i jak najlepiej rozwiązać wyświetlanie komunikatów, które w tej formie nie działają.

Za wszelkie opinie, porady serdecznie dziękujęsmile.gif

  1. class new_user
  2. {
  3. public $login;
  4. public $pass;
  5. public $re_pass;
  6. public $email;
  7.  
  8. function validate($dane)
  9. {
  10. $dane = htmlspecialchars($dane, ENT_QUOTES);
  11. $dane = mysql_real_escape_string($dane);
  12. {
  13. $dane = addslashes ($dane);
  14. }
  15. return $dane;
  16. }
  17.  
  18. function check_login ()
  19. {
  20. if ($this->login==$this->validate($this->login))
  21. {
  22. $query = mysql_query('SELECT id FROM test WHERE login = "'.$this->login.'"') or die (mysql_error());
  23. if (mysql_num_rows($query) != 0)
  24. {
  25. // login zajęty
  26. $komunikat = 'Wybrany login jest zajęty';
  27. return false;
  28. }
  29. else
  30. {
  31. // login wolny
  32. return $this->login;
  33. }
  34. }
  35. else
  36. {
  37. $komunikat = 'Login zawiera niedozwolone znaki';
  38. return false;
  39. }
  40. }
  41.  
  42. function check_pass ()
  43. {
  44. if ($this->pass==$this->validate($this->pass))
  45. {
  46. if ($this->pass==$this->re_pass)
  47. {
  48. if (strlen($this->pass)>5)
  49. {
  50. return md5($this->pass);
  51. }
  52. else
  53. {
  54. $komunikat = 'Podane hasło jest za krótkie (min. 6 znaków)';
  55. return false;
  56. }
  57. }
  58. else
  59. {
  60. $komunikat = 'Podane hasła są różne';
  61. return false;
  62. }
  63. }
  64. else
  65. {
  66. $komunikat = 'Hasło zawiera niedozwolone znaki';
  67. return false;
  68. }
  69.  
  70. }
  71.  
  72. function check_email ()
  73. {
  74. if (ereg("^[a-z0-9_\\.-]+@([a-z0-9_-]+\\.)+[a-z]{2,}$", $this->email))
  75. {
  76. return $this->email;
  77. }
  78. else
  79. {
  80. $komunikat = 'Podaj poprawny adres e-mail';
  81. return false;
  82. }
  83. }
  84.  
  85. function add_user ()
  86. {
  87. if($this->check_login() && $this->check_pass() && $this->check_email())
  88. {
  89. mysql_query("INSERT INTO test(login,pass,email) VALUES('".$this->check_login()."','".$this->check_pass()."','".$this->check_email()."')");
  90. {
  91. return true;
  92. }
  93. else
  94. {
  95. return false;
  96. }
  97. }
  98. }
  99.  
  100. }
  101.  
  102. $new = new new_user;
  103. $new->login = 'ssssss';
  104. $new->pass = 'aaaaaaaaa';
  105. $new->re_pass = 'aaaaaaaaa';
  106. $new->email = 'ttttt@gggggg.pl';
  107. $nowy = $new->add_user($new);
  108. echo $komunikat;
yevaud
z jakiego powodu nie uzywasz PDO ?
nospor
Cytat
ale za to również nie wyświetla komunikatu

Oczywiscie ze nie
1) poczytaj o zasięgu zmiennych
2) poczytaj o czyms takim jak return, albo wlasciwosci klasy

3)Temat OOP nie do konca powstał na takie tematy. przenosze
yevaud
podejscie z adduser jest dla mnie troche dziwne. Moim zdaniem powinno byc jakies "save" ktore zapamietywaloby identyfikator uzytkownika, albo w ogole powinienes oddzielic warstwe z tym userem, od warstwy zapisujacej dane do bazy

z save wygladaloby to jakos tak

  1. $user = new new_user();
  2. $user->jakiesdane = $dane;
  3. try {
  4. $user->save();
  5. // dodamy mu jeszzce jakies dane
  6. $user->innedane = $dane;
  7. $user->save();
  8. } (..)

generalnie logiczniej bedzie jesli obiekt uzytkownika bedzie reprezentowal jednego konkretnego uzytkownika. Jesli chcesz masowo dodawac uzytkownikow to moim zdaniem powinienes zrobic inna klase - fabryke - ktora bedzie tworzyla obiekty klasy user

  1. $fabryka = new fabryka();
  2. $user = $fabryka->nowyuser();
  3. $user->jakiesdane = $dane;
  4. $user->save(); // insert
  5.  
  6. $user2 = $fabryka->nowyuser();
  7. $user2->jakiesdane = $jakiesdane dla innego usera;
  8. $user2->save(); //insert
  9.  
  10. $user3 = $fabryka->ladujusera($id);
  11. $user3->jakiesdane = $jakiesdane dla innego usera;
  12. $user3->save(); //update
  13.  


moim zdaniem cos w ten desen, ale sie opisalem..
szczypior
Cytat
z jakiego powodu nie uzywasz PDO ?

Gdyż to tylko testowy kod, szybciej pisze się bez PDO. Nacodzień jednak korzystam z dobrodziejstw PDO.

Cytat
podejscie z adduser jest dla mnie troche dziwne

Nie bardzo rozumiem jak mam oddzielić warstwę z userem od zapisywania? Rozumiem, że proponujesz, aby w inny sposób przekazać zvalidowane dane do zapytania SQL, tak? Masz jakąś konkretną propozycję?

Napisany przeze mnie kod miałby służyć do rejestracji użytkowników w serwisie poprzez formularz i miałby operować na otrzymanych danych, więc nie będzie to na masową skalę. Nie mniej jednak nie bardzo rozumiem idee "fabryki". Co ona powinna zawiera/robić?

Wyświetlanie komunikatów udało mi się rozwiązać po wskazówkach Nospor'a:) Czy ten sposób jest OK? Czy jest lepsze rozwiązanie?

Natomiast nadal nie bardzo wiem, jak udoskonalić resztę kodu. Bardzo proszę o porady, pomoc. Teraz wygląda on tak:
  1.  
  2. class new_user
  3. {
  4. public $login;
  5. public $pass;
  6. public $re_pass;
  7. public $email;
  8. public $status;
  9.  
  10. function validate($dane)
  11. {
  12. $dane = htmlspecialchars($dane, ENT_QUOTES);
  13. $dane = mysql_real_escape_string($dane);
  14. {
  15. $dane = addslashes ($dane);
  16. }
  17. return $dane;
  18. }
  19.  
  20. function check_login ()
  21. {
  22. if ($this->login==$this->validate($this->login))
  23. {
  24. $query = mysql_query('SELECT id FROM test WHERE login = "'.$this->login.'"') or die (mysql_error());
  25. if (mysql_num_rows($query) != 0)
  26. {
  27. // login zajęty
  28. $this->status = 'Wybrany login jest zajęty';
  29. return false;
  30. }
  31. else
  32. {
  33. // login wolny
  34. return $this->login;
  35. }
  36. }
  37. else
  38. {
  39. $this->status = 'Login zawiera niedozwolone znaki';
  40. return false;
  41. }
  42. }
  43.  
  44. function check_pass ()
  45. {
  46. if ($this->pass==$this->validate($this->pass))
  47. {
  48. if ($this->pass==$this->re_pass)
  49. {
  50. if (strlen($this->pass)>5)
  51. {
  52. return md5($this->pass);
  53. }
  54. else
  55. {
  56. $this->status = 'Podane hasło jest za krótkie (min. 6 znaków)';
  57. return false;
  58. }
  59. }
  60. else
  61. {
  62. $this->status = 'Podane hasła są różne';
  63. return false;
  64. }
  65. }
  66. else
  67. {
  68. $this->status = 'Hasło zawiera niedozwolone znaki';
  69. return false;
  70. }
  71.  
  72. }
  73.  
  74. function check_email ()
  75. {
  76. if (ereg("^[a-z0-9_\\.-]+@([a-z0-9_-]+\\.)+[a-z]{2,}$", $this->email))
  77. {
  78. return $this->email;
  79. }
  80. else
  81. {
  82. $this->status = 'Podaj poprawny adres e-mail';
  83. return false;
  84. }
  85. }
  86.  
  87. function add_user ()
  88. {
  89. if($this->check_login() && $this->check_pass() && $this->check_email())
  90. {
  91. mysql_query("INSERT INTO test(login,pass,email) VALUES('".$this->check_login()."','".$this->check_pass()."','".$this->check_email()."')");
  92. {
  93. $this->status = 'Użytkownik dodany poprawnie.';
  94. return true;
  95. }
  96. else
  97. {
  98. $this->status = 'Wystąpił błąd podczas dodawania użytkownika.';
  99. return false;
  100. }
  101. }
  102. }
  103.  
  104. }
  105.  
  106. $new = new new_user;
  107. $new->login = 'sssssgs';
  108. $new->pass = 'aaaaaaaaa';
  109. $new->re_pass = 'aaaaaaaaa';
  110. $new->email = 'tttttg@ggggg.pl';
  111. $nowy = $new->add_user($new);
  112. echo $new->status;
  113.  
Crozin
1. new new_user();. Czy taki zapis ma dla Ciebie sens? Wywal ten śmieszny przedrostek "new_" z nazwy.
2. Metoda validate - przecież ona niczego nie sprawdza - jedyne co robi to przygotowuje dane do zapisu do bazy.
2.1. Tym powinno zajmować się PDO (czy coś takiego).
2.2. Usuwanie "dobrodziejstw" magic quotes powinno być raczej gdzie indziej.
2.3. htmlspecialchars powinno używać się przed wyświetleniem danych, a nie ich zapisywaniem.
3. Status nowego użytkownika to może być "zarejestrowany", "autoryzowany" itp., a nie "login jest zajęty" - od czegoś takiego są wyjątki.
4. Od sprawdzania poprawności emaila masz filter_var, a nie eregi (notabene oznaczone już jako deprecated)
5. Twój obiekt to: reprezentant użytkownika, walidator danych z formularza, warstwa zapisująca dane po rejestracji, jakiś ogólny filtr dla danych trafiających do bazy - a jedna z podstawowych zasad OOP brzmi: jeden obiekt - jedno zadanie.
szczypior
Cytat
2. Metoda validate - przecież ona niczego nie sprawdza - jedyne co robi to przygotowuje dane do zapisu do bazy.

Metoda ta usuwa, zastępuje niedozwolone znaki, następnie w ifie porównuję login wprowadzony przez użytkownika z tym, który został przepuszczony przez validację. Jeśli oba są jednakowe to login uznany jest za poprawny.

Cytat
2.1. Tym powinno zajmować się PDO (czy coś takiego).

PDO będzie, nie użyłem go tylko w tym kodzie "szkoleniowym"

Cytat
2.2. Usuwanie "dobrodziejstw" magic quotes powinno być raczej gdzie indziej.

Chodzi Ci o to, że powinno być uaktywnione na serwerze?

Cytat
5. Twój obiekt to: reprezentant użytkownika, walidator danych z formularza, warstwa zapisująca dane po rejestracji, jakiś ogólny filtr dla danych trafiających do bazy - a jedna z podstawowych zasad OOP brzmi: jeden obiekt - jedno zadanie.

Nie bardzo rozumiem, co i jak mam jeszcze podzielić. Możesz to napisać łopatologiczniej? winksmiley.jpg

Poniżej kod po poprawkach, proszę o kolejne uwagi i wskazówki:)

  1.  
  2. try {
  3. $pdo = new PDO('mysql:host=localhost;dbname=baza', 'log', 'pass');
  4. $pdo -> query("SET NAMES 'utf8'");
  5. //echo 'Połączenie nawiązane!';
  6. }
  7. catch(PDOException $e)
  8. {
  9. echo 'Połączenie nie mogło zostać utworzone: ' . $e->getMessage();
  10. die;
  11. }
  12.  
  13. class user
  14. {
  15. public $login;
  16. public $pass;
  17. public $re_pass;
  18. public $email;
  19.  
  20. private $pdo; //obiekt klasy PDO
  21.  
  22.  
  23. public function __construct(&$pdo)
  24. {
  25. $this->pdo =& $pdo; //przekazanie obiektu PDO do klasy.
  26. }
  27.  
  28.  
  29. function validate($dane)
  30. {
  31. $dane = htmlspecialchars($dane, ENT_QUOTES);
  32. //$dane = mysql_real_escape_string($dane);
  33. {
  34. $dane = addslashes ($dane);
  35. }
  36. return $dane;
  37. }
  38.  
  39. function check_login ()
  40. {
  41. if ($this->login != $this->validate($this->login))
  42. {
  43. throw new Exception('Login zawiera niedozwolone znaki');
  44. }
  45.  
  46. $sql = "SELECT id FROM `test` WHERE login= :login";
  47. $start = $this->pdo->prepare($sql);
  48. $start->bindParam(':login' , $this->login , PDO::PARAM_STR);
  49. $start->execute();
  50. $result=$start->rowCount();
  51. $start->closeCursor();
  52.  
  53. //$query = mysql_query('SELECT id FROM test WHERE login = "'.$this->login.'"') or die (mysql_error());
  54.  
  55. if ($result != 0)
  56. {
  57. throw new Exception('Wybrany login jest zajęty');
  58. }
  59. return $this->login;
  60. }
  61.  
  62. function check_pass ()
  63. {
  64. if ($this->pass != $this->validate($this->pass))
  65. {
  66. throw new Exception('Hasło zawiera niedozwolone znaki');
  67. }
  68.  
  69. if ($this->pass != $this->re_pass)
  70. {
  71. throw new Exception('Podane hasła są różne');
  72. }
  73.  
  74. if (strlen($this->pass)<6)
  75. {
  76. throw new Exception('Podane hasło jest za krótkie (min. 6 znaków)');
  77. }
  78. return md5($this->pass);
  79. }
  80.  
  81. function check_email ()
  82. {
  83. if (filter_var($this->email, FILTER_VALIDATE_EMAIL))
  84. {
  85. return $this->email;
  86. }
  87. throw new Exception('Podaj poprawny adres e-mail');
  88. }
  89.  
  90. function save()
  91. {
  92. if($this->check_login() && $this->check_pass() && $this->check_email())
  93. {
  94. //mysql_query("INSERT INTO test(login,pass,email) VALUES('".$this->check_login()."','".$this->check_pass()."','".$this->check_email()."')");
  95.  
  96. $sql = "INSERT INTO `test` (login,pass,email) VALUES (:login,:pass,:email)";
  97. $start = $this->pdo->prepare($sql);
  98. $start->bindParam(':login' , $this->check_login() , PDO::PARAM_STR);
  99. $start->bindParam(':pass' , $this->check_pass() , PDO::PARAM_STR);
  100. $start->bindParam(':email' , $this->check_email() , PDO::PARAM_STR);
  101. $result=$start->execute();
  102. $start->closeCursor();
  103. echo $result;
  104. if ($result == 1)
  105. {
  106. return true;
  107. }
  108. else
  109. {
  110. throw new Exception('Wystąpił błąd podczas dodawania użytkownika.');
  111. }
  112. }
  113. }
  114.  
  115. }
  116.  
  117. try
  118. {
  119. $new = new user($pdo);
  120. $new->login = 'ssss#%@#&;"sg/s0aa';
  121. $new->pass = 'aaaaaaaaa';
  122. $new->re_pass = 'aaaaaaaaa';
  123. $new->email = 'tttttg@ggggg.pl';
  124. $new->save();
  125. echo 'Użytkownik dodany pomyślnie';
  126. }
  127. catch (Exception $error)
  128. {
  129. echo $error->getMessage();
  130. }
  131.  
  132.  


Za dalsze uwagi, będę bardzo wdzięczny smile.gif

W kodzie, jak widać użyłem już PDO. Co jeszcze można/należałoby poprawić ?smile.gif
Maciekbjw
Kolego według mnie nie potrzebnie pakujesz całą funkcjonalność do jednej klasy.
Model MVC się kłania.

Zrób osobno akcje, osobną klasę do walidacji danych, osobną do zapisu usera do bazy (tam metody zapisujace, a takze sprawdzajace dostepnosc jakiegos loginu). W ten sposób będzie to miało ręce i nogi smile.gif bo to co przedstawiles to faktycznie klasy ale nijak ma sie to do sensu programowania obiektowego smile.gif
szczypior
Cytat(Maciekbjw @ 19.09.2010, 20:55:38 ) *
Kolego według mnie nie potrzebnie pakujesz całą funkcjonalność do jednej klasy.
Model MVC się kłania.

Zrób osobno akcje, osobną klasę do walidacji danych, osobną do zapisu usera do bazy (tam metody zapisujace, a takze sprawdzajace dostepnosc jakiegos loginu). W ten sposób będzie to miało ręce i nogi smile.gif bo to co przedstawiles to faktycznie klasy ale nijak ma sie to do sensu programowania obiektowego smile.gif


Tzn mówisz, żeby zrobić osobno klasę do walidacji i zapisu, następnie wywoływać je po kolei?
  1. $check = new validate;
  2. $check ->login = 'ssss#%@#&;"sg/s0aa';
  3. $check ->pass = 'aaaaaaaaa';
  4. $check ->re_pass = 'aaaaaaaaa';
  5. $check ->email = 'tttttg@ggggg.pl';
  6.  
  7. $new = new user($pdo);
  8. $new->login = $check ->login;
  9. $new->pass = $check ->pass;
  10. $new->email = $check ->email;
  11. $new->save();

Tak miałoby wyglądać ich wywołanie?
Ziem
Raczej nie chodzi o to.
Powinieneś zakupić jakąś książkę omawiającą OOP - na pewno dużo Ci da i odpowie na wiele pytań. Zobaczysz jak to wszystko wygląda 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.