Pomoc - Szukaj - Użytkownicy - Kalendarz
Pełna wersja: [ZendFramework] Dziedziczenie po Zend_Controler_Action a metoda init()...
Forum PHP.pl > Forum > PHP > Frameworki
mxc
To mój pierwszy post na forum smile.gif

Wiec Witam Wszystkich ( << O tym ze trafiłem tutaj bo pokochałem tworzenie stron www pisać chyba nie muszę bo widać to po tym zdaniu nawet ^^ )

Ale do rzeczy.. - bawię się Zend_Frameworkiem - pomyślałem ze zrobię sobie moduł 'panel' dzięki któremu będę zarządzał stroną....

No i dobrze... będą kontrolery:
* newsy (do edycji aktualności),
* linki(do edycji linków),
* strony(do edycji podstron takich jak o_mnie, home itp...),
* galeria...
* ipcwp ( i pewnie coś w przyszłości )

pomyślałem ze sobie zrobię Panel_Controller_Action który będzie dziedziczył po Zend_Controller_Action i w init() sprawdzal czy gosc jest zalogowany czy nie...

i teraz problem:
Nie mam pomysłu jak to zrobić w taki sposób by nie móc nadpisać metody init() w klasie Panel_IndexController dziedziczącej po Panel_Controller_Action
Bo jeżeli gdzieś to zrobię to sprawdzanie czy gość jest zalogowany czy nie zostanie nadpisane - czyli leżymy winksmiley.jpg
oczywiście mogę użyć parent::init() i po problemie!
Ale co jak o tym zapomnę ?

Nie jestem obiektowym super programistą...
Ale jestem po "Head First - Design Patterns" <- cholernie polecam książeczkę smile.gif
I wiem ze w "Obiektowe" istnieje jakiś mądrzejszy sposób na wykonanie tego co chce osiągnąć...

Proszę o wskazówki!
Z góry dzięki!
Sajrox
Nie wiem czy dobrze zrozumiałem ale ja rozwiązałem to tak:

Sprawdzanie zalogowanej osoby (gośc czy nie gość) ustawiem w pluginie w metodzie dispatchLoopStartup()

Co do Kontrolerów to każdy kontroler dziedziczy po kontrolerze globalnym

  1. class User_OrdersController extends User_InitController {
  2. public function init() {
  3. //Uruchamiamy metodę init z kontrolera globalnego
  4. parent::init();
  5. }
  6. }



Tworzę tutaj metodę init() tak jak w kontrolerze globalnym i w niej wywołuje:
  1. parent::init();


Sam kontroler gobalny wygląda talk:
  1. abstract class User_InitController extends Zend_Controller_Action {
  2.  
  3. public function init() {
  4.  
  5. $userSession = new Zend_Session_Namespace('userSession');
  6. $this->userAuth = $userSession->userAuth;
  7.  
  8. // ...
  9. }
  10. //...
mxc
Dzięki Sajrox za zainteresowanie...
Dobrze mnie zrozumiałeś... aczkolwiek właśnie chcę uniknąć czegoś takiego:

  1. class User_OrdersController extends User_InitController {
  2. public function init() {
  3. //Uruchamiamy metodę init z kontrolera globalnego
  4. parent::init(); //<< dokladnie tego...
  5. }
  6. }


Z założenia ma to być kod wielokrotnego wykorzystania...
Nie chce być zmuszony pamiętać każdorazowo o tej linijce...
Powiem szczerze sam nie wiem dlaczego ^^
Po prostu coś mi mówi ze to nie powinno działać w ten sposób..
...ze istnieje jakieś inne mądrzejsze rozwiązanie winksmiley.jpg
Być może uparciuch ze mnie i szukam problemów na siłę winksmiley.jpg

Ale nie chodzi tylko o auth użytkowników - chciałem sobie dodatkowo dopisać kilka
rzeczy ułatwiających pracę takich jak np. autoDołączanie CSS, JS
Ogólnie chce żeby kontroler globalny zawsze wykonał kilka rzeczy - a dopiero potem pozwolił pracować normalny kontrolerom...

Myślałem nad tym a żeby takie akcje wykonywały się w konstruktorze kontrolera globalnego
ale.... hymmm smile.gif OK - chwila winksmiley.jpg Coś wymyśliłem smile.gif

________________________________________________________________________________
__________
A jednak nie do końca się udało smile.gif

wcześniej też miałem podobny pomysł ale używałem:
  1. parent::__construct()
  2. parent::init()

co wiadomo powodowało ze najpierw wykonywany był init() z Panel_IndexController a dopiero potem init() rodzica
bo Zend_Controller_Action wywołuje
  1. $this->init()

w konstruktorze

Oto i on:
  1. <?php
  2. abstract class My_Controller_Action extends Zend_Controller_Action
  3. {
  4. public function __construct(Zend_Controller_Request_Abstract $request, Zend_Controller_Response_Abstract $response, array $invokeArgs = array())
  5. {
  6. $this->setRequest($request)
  7. ->setResponse($response)
  8. ->_setInvokeArgs($invokeArgs);
  9. $this->_helper = new Zend_Controller_Action_HelperBroker($this);
  10.  
  11. //Tutaj kod :)
  12. echo ' Krok1 >> ';
  13.  
  14. $this->init();
  15. }
  16. }

  1. abstract class My_Panel_Controller_Action extends My_Controller_Action
  2. {
  3. public function __construct(Zend_Controller_Request_Abstract $request, Zend_Controller_Response_Abstract $response, array $invokeArgs = array())
  4. {
  5. $this->setRequest($request)
  6. ->setResponse($response)
  7. ->_setInvokeArgs($invokeArgs);
  8. $this->_helper = new Zend_Controller_Action_HelperBroker($this);
  9.  
  10. //Tutaj kod :)
  11. echo ' Krok2 >> ';
  12.  
  13. $this->init();
  14. }
  15. }

  1. class Panel_IndexController extends My_Panel_Controller_Action
  2. {
  3. public function init()
  4. {
  5. echo 'Krok3 ;) ';
  6. }
  7.  
  8. public function indexAction()
  9. {
  10.  
  11. }
  12. }


Uświadomcie mnie dlaczego wynikiem jest:
Krok2 >> Krok3
a nie:
Krok1 >> Krok2 >> Krok3
-=Peter=-
Dlatego, gdyż w drugiej klasie nadpisujesz konstruktor tej pierwszej. Konstruktor klasy My_Controller_Action się nie wykonuje.

Nie rozumiem, co chcesz osiągnąć tym sposobem, "zaoszczędzić" 1 linijkę kodu?

Miej zawsze odruch wywoływania w init metody rodzica (parent::init), gdyż nawet jeśli początkowo klasa nadrzędna ma pustą metodę init, to w czasie pisania aplikacji możesz dojść do wniosku, że jednak coś zrefaktorujesz i ją zapełnisz lub też zmienisz klasę bazową - oszczędzisz sobie później nerwów z odnajdowaniem tego, że zapomniałeś wywołać parent::init().
seth-kk
proponuje jeszcze zapoznac sie z samym oop a zwlaszcza ze slowkiem kluczowym final
darko
Odnośnie sprawdzenia czy user jest zalogowany, akurat są bardziej standardowe rozwiązania pod tytułem Zend_Auth i Zend_Acl. W Zend_Acl zarządzasz rolami, zasobami i dostępem ról do zasobów. W Bootstrapie na podstawie Zend_Auth sprawdzasz czy została określona rola użytkownika i w zależności albo ustawiasz domyślną, albo odczytaną z getStorage()->read()->role.
Najlepiej byłoby napisanie pluginu, do którego, w konstruktorze przekazujesz instancję Twojego Acl'a. W pluginie tym implementujesz jedną metodę o nazwie preDispatch. Metoda ta jest wywoływana za każdym żądaniem, jeszcze przed wywołaniem kontrolera. W ten sposób masz pewność, że plugin zostanie wywołany przy każdym żądaniu. Polecam poszukać informacji o Zend_Auth + Zend_Acl, właściwie od tego są te klasy w ZF.
phpion
Cytat(seth-kk @ 8.12.2009, 01:53:43 ) *
proponuje jeszcze zapoznac sie z samym oop a zwlaszcza ze slowkiem kluczowym final

Racja, final jest tym, czego potrzebujesz.
  1. final public function init() {}

Dzięki temu nie będzie możliwe nadpisanie tej metody, a takowa próba zostanie wychwycona odpowiednim błędem. Jeśli więc gdziekolwiek w klasach dziedziczących utworzysz metodę init() to otrzymasz błąd.
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.