Pomoc - Szukaj - Użytkownicy - Kalendarz
Pełna wersja: MVC, Controller i Model -> prośba o opinię
Forum PHP.pl > Forum > PHP > Object-oriented programming
LowiczakPL
Witam

Dopiero uczę się obiektowości i chcę napisać sobie lekki framework MVC, na potrzeby prostych stron z systemem CMS.

Napisałem system rejestracji użytkownika, aktywacji konto i logowania, chodzi o ocenę tego przez doświadczone osoby, czy dobrze rozumiem MVC.


  1. <?php
  2. namespace Controllers;
  3.  
  4. use Core\View;
  5. use Core\Controller;
  6. use Helpers\Session;
  7. use Helpers\Url;
  8. use Helpers\Token;
  9. use Helpers\ClientIP;
  10. use Helpers\Password;
  11.  
  12. class Users extends Controller
  13. {
  14. private $_model_users;
  15.  
  16. public function __construct()
  17. {
  18. parent::__construct();
  19. $this->_model_users = new \Models\Users();
  20. }
  21.  
  22. public function logowanie()
  23. {
  24. $data['meta_title'] = 'Zaloguj się';
  25. $data['meta_description'] = 'Logowanie w ...';
  26. View::render('users/logowanie', $data);
  27. }
  28.  
  29. public function rejestracja()
  30. {
  31. if (Session::get('loggedin')) {
  32. Url::redirect(URL_ZALOGOWANY);
  33. }
  34.  
  35. $data['meta_title'] = 'Zarejestruj się';
  36. $data['meta_description'] = 'Rejestracja w ...';
  37. View::render('users/rejestracja', $data);
  38. }
  39.  
  40. public function zalogowany()
  41. {
  42. if (!Session::get('loggedin')) {
  43. Url::redirect(URL_LOGOWANIE);
  44. }
  45.  
  46. $data['meta_title'] = 'Zalogowany';
  47. View::render('users/zalogowany', $data);
  48. }
  49.  
  50. public function loguj()
  51. {
  52. if (Session::get('loggedin')) {
  53. Url::redirect(URL_ZALOGOWANY);
  54. }
  55.  
  56. $FiltrujZmienna = new \Helpers\FiltrujZmienna();
  57. $email = $FiltrujZmienna->postStr('email');
  58. $haslo = $FiltrujZmienna->postStr('haslo');
  59.  
  60. if (empty($email) || empty($haslo)){
  61. Session::set('blad_logowanie', 'Podaj e-mail i hasło');
  62. Url::redirect(URL_LOGOWANIE);
  63. }
  64. elseif (Password::verify($haslo, $this->_model_users->getHaslo($email)) == false) {
  65. Session::set('blad_logowanie', 'Błędny email lub hasło');
  66. Url::redirect(URL_LOGOWANIE);
  67. }
  68.  
  69. if (!$error) {
  70. Session::set('loggedin', true);
  71. Session::set('userID', $this->_model_users->getID($email));
  72. Url::redirect(URL_ZALOGOWANY);
  73. }
  74. }
  75.  
  76. public function wyloguj()
  77. {
  78. Session::destroy();
  79. Url::redirect();
  80. }
  81.  
  82. public function rejestruj()
  83. {
  84. $FiltrujZmienna = new \Helpers\FiltrujZmienna();
  85.  
  86. if ($this->_model_users->getID($FiltrujZmienna->postStr('email')) > 0) {
  87. Session::set('blad_rejestracja','<br /><div style="color:red;">Istnieje już taki e-mail w systemie, podaj inny adres e-mail.</div><br />');
  88. Url::redirect(URL_REJESTRACJA);
  89. }
  90. else {
  91. $dane=array(
  92. 'token' => Token::get(15),
  93. 'imie' => $FiltrujZmienna->postStr('imie'),
  94. 'nazwisko' => $FiltrujZmienna->postStr('nazwisko'),
  95. 'login' => $FiltrujZmienna->postStr('email'),
  96. 'haslo' => Password::make($FiltrujZmienna->postStr('haslo')),
  97. 'data' => date('Y-m-d h:m:s'),
  98. 'ip' => ClientIP::get(),
  99. 'aktywny' => '0'
  100. );
  101. $this->_model_users->insert($dane);
  102. Url::redirect(URL_ZAREJESTROWANY);
  103. }
  104. }
  105.  
  106. public function zarejestrowany()
  107. {
  108. $data['meta_title'] = 'Zarejestrowany';
  109. $data['meta_description'] = '';
  110. View::render('users/zarejestrowany', $data);
  111. }
  112.  
  113. public function aktywacja($token)
  114. {
  115. $FiltrujZmienna = new \Helpers\FiltrujZmienna();
  116. $id = $this->_model_users->checkToken($FiltrujZmienna->Str($token);
  117.  
  118. if ($id > 0) {
  119. $this->_model_users->update(array('aktywny'=>1), array('id'=>$id)));
  120. $data['aktywacja_yes'] = 1;
  121. $data['aktywacja_not'] = 0;
  122. }
  123. else {
  124. $data['aktywacja_yes'] = 0;
  125. $data['aktywacja_not'] = 1;
  126. }
  127.  
  128. View::render('users/aktywacja', $data);
  129. }
  130.  
  131. }


  1. <?php
  2.  
  3. namespace Models;
  4.  
  5. class Users extends \Core\Model{
  6.  
  7. public function __construct(){
  8. parent::__construct();
  9. }
  10.  
  11.  
  12. public function getHaslo($login){
  13. $data = $this->_db->select("SELECT haslo FROM ".DB_PREFIX."users WHERE login = :login",
  14. array(':login' => $login));
  15. return $data[0]->haslo;
  16. }
  17.  
  18. public function getID($login){
  19. $data = $this->_db->select("SELECT id FROM ".DB_PREFIX."users WHERE login = :login",
  20. array(':login' => $login));
  21. return $data[0]->id;
  22. }
  23.  
  24. public function checkToken($token){
  25. $data = $this->_db->select("SELECT id FROM ".DB_PREFIX."users WHERE token = :token",
  26. array(':token' => $token));
  27. return $data[0]->id;
  28. }
  29.  
  30. public function insert($array){
  31. return $this->_db->insert(DB_PREFIX.'users',$array);
  32. }
  33.  
  34. public function update($array, $where){
  35. return $this->_db->update(DB_PREFIX.'users',$array, $where);
  36. }
  37. }
  38.  
rad11
Do oceny powinieneś raczej dac to co robią klasy Core`owe czyli główny kontroler, model i widok itd.
LowiczakPL
Ale one teoretycznie nic nie robią dlatego nie dawałem bo po co dawać Corową klasę kontrolera jak jest w niej tylko uruchamiana klasy widoku.

Dla mnie Core Class to kontroler i model usera ale to pewno dlatego że dopiero się uczę OOP stare przyzwyczajenia nie pozwalają mi pisać czysto obiektowo tylko funkcje owijam w klasy.

Dlatego liczę na kilka cennych uwag aby ruszyć z miejsca.

  1. <?php
  2.  
  3. namespace Core;
  4.  
  5. use Core\View;
  6.  
  7. abstract class Controller
  8. {
  9. public $view;
  10.  
  11. public function __construct()
  12. {
  13. $this->view = new View();
  14. }
  15. }
  16.  
rad11
No ok. A gdzie robisz rozruch całego frameworka i parsowanie adresow ? Jaki jest flow ?
com
polecam poczytać o psr, czyli spisany zbiór zasad standardu na którym warto sie opierać wpisz w google psr php, jest nawet po polsku ale nwm czy wszystko przetłumaczyli, choć ang nie powinie być problemem wink.gif co do kodu powyżej z ost posta to widok przekazuj jako zależność, nie twórz go w w klasie, tutaj warto poczytać o depedency injection i o IoC wink.gif

Jak zajrzysz do psr to tam zalecają nie używać uderscore dla prywatnych, no i raczej teraz piszemy stylem cammelCase smile.gif

No i wykorzystaj autoloading z psr-4 ( jest jeszcze psr-0, ale to już można zapomnieć wink.gif)

W dodatku staraj się trzymać jednego standardu bo raz klamra w tej samej lini raz w innej, dla metod i klas w nowej smile.gif
LowiczakPL
Ale to jest Abstrakcyjna klasa kontrolera stworzona tylko do uruchamiania widoku, ewentualnie wersji językowej ale nie zaimplementowałem jej jeszcze.

Co do uderscore to spodobał mi się ten sposób eksponowania zmienny prywatnych, ale nie wiem czy jest sens wyróżniać zmienne prywatne, publiczne i chronione, czy to w ogóle się przydaje?
com
owszem, ale na etapie projektowania powinieneś brać pod uwagę to, że ktoś kto powiedzmy będzie chciał skorzystać z Twojego framewoka, zamiast tego widoku który mu serwujesz zechce użyć innego, wtedy by musiał cały kod zmienić, żeby to zrobić , poza tym skoro to jest kontroler to powinien posiadać info o widoku ale widok nie powinien się tworzyć sam. Weźmy przykład bazy danych, chcesz ja wywołać np w 3 klasach, nie zależnych od siebie, to teraz dla każdej z nich musisz stworzyć nowa instancje, na nowo się połączyć etc...

osobiście nigdy nie używałem i nie mam problemu, wystarczy dobre IDE smile.gif

I tak na przyszłość nie mieszaj polskich nazw z angielskim bo wyjdzie z tego straszny bałagan i szybko sam się zgubisz smile.gif angielski to jednak standard wink.gif
LowiczakPL
Model usera podobnie jak klasa Core jest jedynie abstrakcją inicjującą połączenie z bazą, Model tworzy instancję i sprawdza jej stan nie pozwalając na ponowne ustanowienie połączenia z tą samą bazą danych.

Tworząc abstrakcyjny Model2 mogę uruchomić całkowicie inną bazę danych, może to na wyrost zrobiłem ale tak samo wyszło.

Co do obsługi bazy to miałem wcześniej zaimplementowane RedBeanPHP ale przemyślałem sprawę że armata na muchę nie jest mi potrzebna dlatego zmieniłem szybko model na PDO, oczywiście brancha z RedBeanPHP zachowałem w razie czego wink.gif

Cytat(com @ 3.01.2016, 18:01:43 ) *
... I tak na przyszłość nie mieszaj polskich nazw z angielskim bo wyjdzie z tego straszny bałagan i szybko sam się zgubisz smile.gif angielski to jednak standard wink.gif


Wykorzystuję w tym projekcie pojedyncze klasy, które kiedyś napisałem, ale powoli zmienię nazewnictwo w jednym stylu czyli tak jak piszesz.
com
No właśnie tworząc Model2 a ja nie chcę Modelu2 tylko zrobić to w Model, a się w takim przypadku nie da wink.gif Ograniczasz i zamykasz swój kod wokół jednej słusznej implementacji co nie jest dobre wink.gif

a wystarczyło by zrobić tak:
  1. $pdo = new PDO('mysql...');
  2. $model = new User($pdo); //Model
  3. $pdo2 = new PDO('sqlite...');
  4. $model2 = new Other($pdo2); //Model
  5.  
  6. $controller = Controller($pdo);


Cytat
Wykorzystuję w tym projekcie pojedyncze klasy, które kiedyś napisałem, ale powoli zmienię nazewnictwo w jednym stylu czyli tak jak piszesz.


Jasne, rozumiem smile.gif
Spawnm
Zapoznaj się z http://www.php-fig.org/
com
pisałem przecież o tym , ale nie dałem linka wink.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.