class Router { public function route() { $controler = new Controler(); $controler->run(); } } class Controler { public function run() { $view = new View($data); $view->render(); } } class View { public function render($data) { if (/* użytkownik jest administratorem */) { } if (/* użytkownik jest moderatorem */) { } // Przekieruj do strony logowania } }
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:
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:
if (CurrentUser::hasAccess('backend', 'administrator_panel')) {
Wygląda to bardzo czytelnie. Obiekt CurrentUser może być częściowo inicjowany w Router'ze:
CurrentUser::setUser(User::findById($_SESSION['id']));
A częściowo w Controler'ze:
CurrentUser::setGuard('backend', new BackendGuard());
Funkcja CurrentUser::hasAccess mogłaby wyglądać tak:
return self::$guard[$module]->hasAccess(self::$user, $access); }
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

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.