Pomoc - Szukaj - Użytkownicy - Kalendarz
Pełna wersja: Wywołanie kontrolera
Forum PHP.pl > Forum > PHP
cer98
Mam problem. Otóż nie mogę wyważyć w jaki sposób odpalać te kontrolery we frameworku, mvc. Pierwszy sposób zawodzi, gdy znajdzie się w Managerze metoda z walidacją, ponieważ muszę użyć instrukcji if by sprawdzić, czy została wywołana i jeśli tak wywołać również walidację. Natomiast druga zawodzi w momencie, gdy ktoś chce złamać zabezpieczenia, bowiem metodę widać w adresie strony. Proszę o rady. Przejrzałem frameworki, ale nie znalazłem odpowiedzi.


Adres:
  1. index.php?module=user&action=shownotactive&other=1_2



1) metoda pierwsza

  1. class UserController{
  2.  
  3. public function __construct($action, Array $other){
  4.  
  5. $usermanager = new UserManager;
  6. $usermanager->$action($other);
  7.  
  8. }
  9.  
  10. }



2) metoda druga

  1.  
  2. class UserController{
  3.  
  4. private $index;
  5.  
  6. public function __construct($action){
  7.  
  8. $usermanager = new UserManager;
  9. $this->index->$action;
  10.  
  11. }
  12.  
  13. public function set(){
  14.  
  15. if(isset($this->index)){
  16.  
  17. $usermanager->showPanel();
  18.  
  19. }
  20.  
  21. if($this->index == 'shownotactive'){
  22.  
  23. $usermanager->shownotactive();
  24.  
  25. }
  26.  
  27. if($this->index == 'addnewuser'){
  28.  
  29. $usermanager->addnewuser();
  30.  
  31. }
  32.  
  33. }
bastard13
Tym, jaka akcja dla danego kontrolera powinna zostać wykonana zajmuje się front controller.
Jeżeli nie ma żądanego kontrolera lub brakuje akcji dla danego kontrolera, to powinien (front controller) w tym miejscu zwrócić wyjątek.
Coś w tym stylu, załóżmy, że metoda uruchamiająca odpowiednią akcję nazywa się run:
  1. public function run()
  2. {
  3. $request = $this->getRequest(); //metoda request powinna zwracać obiekt z danymi dotyczącymi requestu
  4. $controllerName = $request->getControllerName(); //zwraca nazwę kontrolera lub nazwę domyślnie ustawioną, gdy url jest bez parametrów
  5. $actionName = $request->getActionName(); //analogicznie jak wyżej
  6. try {
  7. $controller = new $controllerName; //autoloader powinien wyrzucić wyjątkiem, jeżeli nie znajdzie kontrolera
  8. $controller->setRequest($request); //request powinien zostać przekazany do kontrolera
  9. }
  10. catch(Autoloader_Exception $e)
  11. {
  12. throw new Controller_Exception('Kontroler ' . $controllerName .' nie istnieje.'); //wyrzucone, gdy autoloader nie znajdzie klasy
  13. }
  14.  
  15. if(!method_exists($controller, $actionName))
  16. throw new Controller_Exception('Akcja '.$actionName.' nie istnieje.'); //wyrzucane, gdy brakuje metody
  17.  
  18. $controller->{$actionName}; //wykonanie akcji, możesz zwracać wynik, jeżeli zachodzi taka potrzeba.
  19. }

A kod kontrollera wygląda np. tak:
  1. Controller_A {
  2. public function foo() {}//gdy url: www.site.com/a/foo
  3. public function boo() {}//gdy url: www.site.com/a/boo
  4. }

Radzę zastosować zamiast takich urli: www.site.com/index.php?module=user&action=shownotactive&other=1_2 coś takiego: www.site.com/user/shownotactive?other=1_2 wygląda o wiele ładniej. Wartość parametru other powinna być dostępna z obiektu Request, a nie przekazywana jako parametr metody akcji.
cer98
Dzięki wielkie, pomogło

Mógłbyś wytłumaczyć budowę requestu w tym przykładzie ?

Czy getRequest powinien zwracać referencję do tablicy ?
bastard13
Metoda getRequest() powinna zwracać obiekt klasy Request, która zawiera informacje nt. aktualnego requestu, czyli jej budowa może wyglądać mniej więcej tak:
  1. class Request {
  2. private $_controllerName;
  3. private $_actionName;
  4. private $_params = array(); //dobrze byłoby, gdyby istniał podział na parametry przekazane za pomocą metody GET i POST
  5. public function getControllerName($default = 'index') {} //jeżeli nie został przekazany w url kontroler, to zostaje zwrócony domyślny
  6. public function getActionName($default = 'index') {} //analogicznie j.w.
  7. public function getParams($method = Request::ALL) {} //zwraca wszystkie parametry. Tutaj radziłbym zastosować jakieś consty do określenia czy wszystkie wysłane postem, getem, czy ogólnie wszystkie
  8. public function getParam($name, $default = null) {} //zwraca wartość parametry lub $default, gdy parametr nie został przekazany
  9. }

Oczywiście to tylko sugestia, bo można spokojnie to rozbudować. Dodatkowo pozostaje decyzja, czy parametry są przekazywane, czy sam obiekt dobiera się do nich z tablic globalnych. To samo tyczy się nazw akcji i kontrolera. Czy pobierać je wewnątrz obiektu klasy, czy może przekazywać. Jeżeli chcesz to wszystko ustawiać to raczej proponowałbym takie dane przekazywać w konstruktorze, a nie za pomocą seterów, ponieważ logika podpowiada, że po utworzeniu obiektu klasy request raczej nie powinien się zmienić.
Temat można rozwinąć, jeżeli zakładasz również obsługę kodu z linii poleceń. W takim wypadku doradzałbym wyciągnięcie klasy bazowej (abstrakcyjnej) wyżej i stworzenie Request_HTTP i Request_CLI lub coś w tym stylu.
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.