Pomoc - Szukaj - Użytkownicy - Kalendarz
Pełna wersja: Sprawdzanie uprawnień użytkownika w modelu MVC
Forum PHP.pl > Forum > PHP > Object-oriented programming
veeveeoor
W uproszczeniu, zgodnie ze wzorcem MVC, w aplikacji można wydzielić Router, który odpala jakiś kontroler, który przy użyciu modelu, generuje widok. W (pseudo)kodzie można wyrazić to tak:

  1. class Router {
  2. public function route() {
  3. $controler = new Controler();
  4. $controler->run();
  5. }
  6. }
  7.  
  8. class Controler {
  9. public function run() {
  10. $view = new View($data);
  11. $view->render();
  12. }
  13. }
  14.  
  15. class View {
  16. public function render($data) {
  17. if (/* użytkownik jest administratorem */) {
  18. echo html_for_admin_from_data($data);
  19. }
  20.  
  21. if (/* użytkownik jest moderatorem */) {
  22. echo html_for_user_from_data($data);
  23. }
  24.  
  25. // Przekieruj do strony logowania
  26. }
  27. }


Ale co powinno być w if'ie? To co wydaje się najrozsądniejsze z mojego punktu widzenia i dobrze wpisuje się w OOP, to coś takiego:

  1. if ($guard->hasAccess($user, 'administrator_panel')) {


Dzięki temu możemy wiele różnych Guard'ów dla np. każdego kontrolera lub grupy kontrolerów. Ale w takim razie jak taki guard ma się znaleźć w funkcji renderującej? Przekazanie go przez argument funkcji jest moim zdaniem bez sensu, bo co jeśli będę potrzebował kolejnego obiektu np. LoginManager, który posiada funkcję redirect_to_login_page? Też przez argument? Potem będę przekazywał 10 różnych obiektów do każdego widoku, a korzystał w danym widoku z jednego lub dwóch. Nie wspomnę już o obiekcie User, który najlepiej gdyby był tworzony raz na początku skryptu np. w funkcji route. Czy zatem mam go przekazać do funkcji Controler:run, a z niej do View::render ?

Więc może inaczej:

  1. if (CurrentUser::hasAccess('backend', 'administrator_panel')) {


Wygląda to bardzo czytelnie. Obiekt CurrentUser może być częściowo inicjowany w Router'ze:

  1. CurrentUser::setUser(User::findById($_SESSION['id']));


A częściowo w Controler'ze:

  1. CurrentUser::setGuard('backend', new BackendGuard());


Funkcja CurrentUser::hasAccess mogłaby wyglądać tak:

  1. public static function hasAccess($module, $access) {
  2. return self::$guard[$module]->hasAccess(self::$user, $access);
  3. }


Jest tylko jedno ale. Taki twór działa globalnie, co moim zdaniem nie jest zbyt dobre. W końcu dążymy do hermetyzacji. Odplamy dwa routery równolegle (trochę abstrakcja smile.gif i klapa.

Mam nadzieję, że dosyć dobrze nakreśliłem problem. Przedsawiłem dwa rozwiązania, które jako tako mogłyby być, ale szukam czegoś lepszego.
viking
Normalnie uprawnienia w widoku przydziela "helper" widoku. Czyli w widoku if (helper.acl==gość or helper.acl=użytkownik) wyświetl coś. A gdzieś globalnie w poziomie aplikacji sprawdzane są i przydzielane uprawnienia z których ten helper czerpie dane.
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-2024 Invision Power Services, Inc.