Pomoc - Szukaj - Użytkownicy - Kalendarz
Pełna wersja: Sesje w Zend Framework
Forum PHP.pl > Forum > PHP
1maciek
Witam,
szukam informacji na temat używania seji w Zend Framework, może ktoś gdzieś widział coś na ten temat, albo wie coś o tym więcej? Może jakiś tutorial z np. systemem logowania?
Z góry wielkie dzięki
Pozdrawiam
Prph
Witam,

Zend samego w sobie machanizmu sesji nie ma. Nic nie stoi na przeszkodzie zeby uzywac $_SESSION.
Przyklad mniej wiecej taki:

1. session_start() w index.php
2. Akcja Logowanie:
- sprawdz czy istnieje uzytkownik w bazie (haslo i login poprawne)
- $_SESSION['zalogowany'] = true;

I juz winksmiley.jpg

Bardzo proste i bardzo nieladne.

Napisalem (moim zdaniem) bardzo ciekawy mechanimz obslugi sesji.

Założenia

Framework udostępnia klasę Rapide_Session do obsługi sesji.

  1. <?php
  2.  
  3. Rapide::loadInterface('Rapide_Session_Interface');
  4. Rapide::loadClass('Rapide_Session_Exception');
  5.  
  6. Rapide::loadInterface('Rapide_Session_Handler_Interface');
  7.  
  8. class Rapide_Session
  9. {
  10. private
  11. $_bSessionStarted = false,
  12. $_sNameSpace;
  13.  
  14. public function __construct($sNameSpace = null)
  15. {
  16. if(isset($sNameSpace))
  17. {
  18. $this->_sNameSpace = $sNameSpace;
  19.  
  20. if(!isset($_SESSION[$this->_sNameSpace]))
  21. $_SESSION[$this->_sNameSpace] = array();
  22. }
  23. }
  24.  
  25. public function getNameSpaceName()
  26. {
  27. return $this->_sNameSpace;
  28. }
  29.  
  30. public function setHandler(Rapide_Session_Handler_Interface $oHandler)
  31. {
  32. if($this->started())
  33. {
  34. $sError = 'Session has already started';
  35. throw new Rapide_Session_Exception($sError);
  36. }
  37.  
  38. (
  39. array(& $oSessionHandler, 'open'),
  40. array(& $oSessionHandler, 'close'),
  41. array(& $oSessionHandler, 'read'),
  42. array(& $oSessionHandler, 'write'),
  43. array(& $oSessionHandler, 'destroy'),
  44. array(& $oSessionHandler, 'gc')
  45. );
  46. }
  47.  
  48. public function started()
  49. {
  50. return (bool)strlen(session_id());
  51. }
  52.  
  53. public function start()
  54. {
  55. if(!$this->started())
  56. {
  57. {
  58. $sError = 'Headers has already sent';
  59. throw new Rapide_Session_Exception($sError);
  60. }
  61.  
  62. }
  63. }
  64.  
  65. public function close()
  66. {
  67. if(!$this->started())
  68. {
  69. $sError = 'Session has not started yet';
  70. throw new Rapide_Session_Exception($sError);
  71. }
  72.  
  73. if(isset($this->_sNameSpace))
  74. $_SESSION[$this->_sNameSpace] = array();
  75. else
  76. $this->destroy();
  77. }
  78.  
  79. public function destroy()
  80. {
  81. if(!$this->started())
  82. {
  83. $sError = 'Session has not started yet';
  84. throw new Rapide_Session_Exception($sError);
  85. }
  86.  
  87. }
  88.  
  89. public function __get($sParameters)
  90. {
  91. if(!$this->started())
  92. {
  93. $sError = 'Session has not started yet';
  94. throw new Rapide_Session_Exception($sError);
  95. }
  96.  
  97. if(isset($this->_sNameSpace))
  98. {
  99. return isset($_SESSION[$this->_sNameSpace][$sParameters]) ?
  100.  $_SESSION[$this->_sNameSpace][$sParameters] :
  101.  null;
  102. }
  103. else
  104. {
  105. return isset($_SESSION[$sParameters]) ?
  106.  $_SESSION[$sParameters] :
  107.  null;
  108. }
  109. }
  110.  
  111. public function __set($sParameters, $mValue)
  112. {
  113. if(!$this->started())
  114. {
  115. $sError = 'Session has not started yet';
  116. throw new Rapide_Session_Exception($sError);
  117. }
  118.  
  119. if(isset($this->_sNameSpace))
  120. $_SESSION[$this->_sNameSpace][$sParameters] = $mValue;
  121. else
  122. $_SESSION[$sParameters] = $mValue;
  123. }
  124.  
  125. public function __isset($sParameters)
  126. {
  127. if(!$this->started())
  128. {
  129. $sError = 'Session has not started yet';
  130. throw new Rapide_Session_Exception($sError);
  131. }
  132.  
  133. if(isset($this->_sNameSpace))
  134. return isset($_SESSION[$this->_sNameSpace][$sParameters]);
  135. else
  136. return isset($_SESSION[$sParameters]);
  137. }
  138.  
  139. public function getNameSpace()
  140. {
  141. if(!$this->started())
  142. {
  143. $sError = 'Session has not started yet';
  144. throw new Rapide_Session_Exception($sError);
  145. }
  146.  
  147. if(isset($this->_sNameSpace))
  148. return $_SESSION[$this->_sNameSpace];
  149. else
  150. return $_SESSION;
  151. }
  152. }
  153.  
  154. ?>


Klasa Rapide_Session jest we frameworku, ale w zasadzie skorzystac z niej powinien tylko sam framework (programista uzyje innej klasy).

Programista ma do uzytku klase Rapide_User

  1. <?php
  2.  
  3. Rapide::loadInterface('Rapide_User_Interface');
  4. Rapide::loadClass('Rapide_User_Exception');
  5. Rapide::loadClass('Rapide_Session');
  6.  
  7. class Rapide_User implements Rapide_User_Interface
  8. {
  9. private
  10. $_oSession,
  11. $_oDataSession;
  12.  
  13. public function __construct()
  14. {
  15. $this->_oSession  = new Rapide_Session('Rapide_User');
  16. $this->_oDataSession = new Rapide_Session('Rapide_User_Data');
  17.  
  18. $this->_oSession->start();
  19. $this->_oDataSession->start();
  20.  
  21. if(!isset($this->_oSession->authenticated))
  22. $this->_oSession->authenticated = false;
  23.  
  24. if(!isset($this->_oSession->groups))
  25. $this->_oSession->groups = array();
  26. }
  27.  
  28. public function getGroups()
  29. {
  30. return $this->_oSession->groups;
  31. }
  32.  
  33. public function setGroups($aGroups = array())
  34. {
  35. if(!is_array($aGroups))
  36. {
  37. $sError = 'Argument 1 for Rapide_User::setGroups() must be an array';
  38. throw new Rapide_User_Exception($sError);
  39. }
  40.  
  41. $this->_oSession->groups = $aGroups;
  42. }
  43.  
  44. public function hasGroup($sGroup)
  45. {
  46. foreach($this->getGroups() as $iKey => $sUserGroup)
  47. {
  48. if($sUserGroup == $sGroup)
  49. return true;
  50. }
  51.  
  52. return false;
  53. }
  54.  
  55. public function isAuthenticated()
  56. {
  57. return $this->_oSession->authenticated;
  58. }
  59.  
  60. public function setAuthenticated($bAuthenticated = true)
  61. {
  62. $this->_oSession->authenticated = (bool)$bAuthenticated;
  63. }
  64.  
  65. public function __get($sParameter)
  66. {
  67. return $this->_oDataSession->$sParameter;
  68. }
  69.  
  70. public function __set($sParameters, $mValue)
  71. {
  72. $this->_oDataSession->$sParameter;
  73. }
  74.  
  75. public function __isset($sParameter)
  76. {
  77. return isset($this->_oDataSession->$sParameter);
  78. }
  79.  
  80. public function destroy()
  81. {
  82. $this->setGroups(array());
  83. $this->setAuthenticated(false);
  84.  
  85. $this->_oSession->close();
  86. $this->_oDataSession->close();
  87. }
  88. }
  89.  
  90. ?>


Kiedy programista chce zapisac dane w sesji, pisze:

  1. <?php
  2. $oUser = new Rapide_User;
  3.  
  4. $oUser->zmienna = 'wartosc';
  5. ?>


Ponadto klasa Rapide_User dostarcza metod dajacych mozliwosc kontrole bezpieczenstwa w aplikacji.
Po zalogowaniu sie nalezy zrobic:
  1. <?php
  2. $oUser->setAuthenticated();
  3. ?>


Pozniej w aby sprawdzic czy uzytkownik zostal zalogowany:

  1. <?php
  2. if($oUser->isAuthenticated()) {
  3. //cos
  4. }
  5. ?>


Przepraszam, ze post napisany na szybko, ale nie mam duzo czasu winksmiley.jpg

Moze pozniej przedstawie lepszy opis i uzycie.

Pozdrawiam, Adrian.
1maciek
wielkie dzięki,
Mam jeszcze takie pytanie (ad. sposobu z $_SESSION): jesli tak zrobie to musze w każdej akcji w każdym kontrolerze sprawdzać czy użytkownik jest zalogowany (wpisująć odpowiednią ściazke może sie dostać gdzie nie powinien), a ja chciałbym tego uniknąć. Jakiś pomysł?

PS Twój pomysł obsługi sesji poprzez klasy frameworka napewno przeanalizuje smile.gif
Pozdrawiam
splatch
[ot]@Prph to wszystko przypomina mi Mojavi.. (poza handlerem)[/ot]
Prph
@Splatch : Haha, po czesci jest to rozwiazanie z mojavi. W zasadzie jedynie obecnosc klasu User, bo cala reszta raczej na byla wzorowana na mojavi. Nie wiem jak jest z najnowszym mojawi ale chyba jeszcze w 3.0 bylo nieco inaczej. W kazdym bardz razie, widac rozwiazanie calkiem dobre smile.gif

@1maciek: Nie musisz w kazdej akcji sprawdzac czy uzytkownij jest zalogowany. Od tego sa pluginy. Akurat pluginy w Zend Frameworku uwazam ze sa bardzo, ale to bardzo dobrze przemyslane i ze sa duzo lepsze od tych z mojavi/symphony. Zerknij do dokumentacji. Jak dobrze pamietam, we Front Controlerze mozna zdefiniowac PluginManagera czy jakos tak. W dokumentacji jest to opisane. Pluginy posiadaja bodajze 4 metody, ktore uruchamiane sa w odpowiedniej chwili w czasie wykonywania dispathcingu (pracy dispatchera).

Rozwiazanie to tak bardzo mi sie spodobalo, ze wykorzystalem je w swoim frameworku. Przyklad:

  1. <?php
  2.  
  3. abstract class Rapide_Plugin implements Rapide_Plugin_Interface
  4. {
  5.  
  6. // metoda wywolana przed rozpoczeciem dispatchingu
  7. public function preDispatchLoop(Rapide_Dispatcher_Token_Interface $oToken)
  8. {
  9. return $oToken;
  10. }
  11.  
  12. // wywolywana po zakonczeniu dispatchingu
  13. public function postDispatchLoop(Rapide_Dispatcher_Token_Interface $oToken)
  14. {
  15. return $oToken;
  16. }
  17.  
  18.  
  19. // wywolana przed uruchomieniem akcji
  20. public function preExecution(Rapide_Dispatcher_Token_Interface $oToken)
  21. {
  22. return $oToken;
  23. }
  24.  
  25. // po zakonczeniu akcji
  26. public function postExecution(Rapide_Dispatcher_Token_Interface $oToken)
  27. {
  28. return $oToken;
  29. }
  30. }
  31.  
  32. ?>


Na bazie tej abstrakcyjnej klasy mozna szybko zbudowac wlasne pluginy, miedzy innymi do bezpieczenstwa:

  1. <?php
  2.  
  3. Rapide_Plugin_Security implements Rapide_Plugin_Interface
  4. {
  5.  
  6.  
  7. public function preExecution(Rapide_Dispatcher_Token_Interface $oToken)
  8. {
  9. if(!isset($_SESSION) || !$_SESSION['zalogowany'])
  10. {
  11. $oToken = new Rapide_Dispatcher_Token('Error', 'Error403');
  12. }
  13. return $oToken;
  14. }
  15. }
  16.  
  17. ?>


W efekcie na ekranie pojawi sie strona z error 403, zamiast np. dodaj newsa.

Oczywiscie zeby to wszystko mialo jakies swoje zastosowanie, nalezy zrobic pliki konfiguracyjne, zeby framework wiedzial, ktore akcjie wymagaja logowania, a ktore nie.

Pozdrawiam, Adrian.
1maciek
OK, fajnie a gdzie (fizycznie) umieścić klasę implementującą plugin, żeby dispatcher z niej korzystał? - ok z tym jakoś dałem sobie rade (chociaż chętnie zobacze jak powinno być to zrobione fachowo smile.gif), ale wywala mi taki błąd
Cytat
Fatal error: Declaration of LoginControl::preDispatch() must be compatible with that of Zend_Controller_Plugin_Interface::preDispatch() in C:\xampp\xampp\htdocs\auth\library\LoginControl.php on line 2



a kod wygląda tak

  1. <?php
  2. class LoginControl implements Zend_Controller_Plugin_Interface {
  3.  
  4. public function preDispatch (Zend_Controller_Dispatcher_Token $action) {
  5. echo 'pD';
  6. return $action;
  7. }
  8. }
  9. ?>


include path mam ustawiona na katalog /library/ tam mam też LoginControl.php
Prph
Witam,

W dokumentacji Zenda masz gdzie powinienes umieszczac swoje wlasne klasy, ktore budujesz z wykorzystaiem klas Zenda.

Strzelam, ze jest to np: MojaAplikacja_Plugin_LoginControl, wiec powinienes umiescic to w katalogu z plikiem Zend.php w katalogu MojaAplikacja/Plugin/LoginControl.php.

Wtedy mozesz zrobic zaladowanie plaginu przez Zend::loadClass('MojaAplikacja_Plugin_LoginControl');

Nie jestem tego pewien, poniewaz nie uzywam Zenda. Wiem o nim troche, bo pod wieloma wzgledami imponuje mi Zend Framework.

Niebawem ukoncze swojego frameworka Rapide. Z racji, ze bardzo podoba mi sie prostota Zenda i organizacja plikow, moj framework implementuje i jedno i drugie winksmiley.jpg Wtedy moge podeslac Ci kod i zorientujesz sie jak to mniej wiecej wyglada w calosc. Zend Framework dostarcza solidnej platformy do zbudowania aplikacji, ale trzeba sie sporo nameczyc, zeby cos odpalic najmniejszym nakladem pracy.

Rapide przede wszystkim poprawnie implementuje MVC. W ZF model jest, kontroler jest, ale widok jest mowiac krotko - nieporozumieniem. Programisci ZF albo wyszli z zalozenia ze i tak w aplikachach webowych prozentowana tresc to HTML, albo pomylilo im sie pojecie szablonow z widokiem winksmiley.jpg Ponadto w Rapide zintegrowalem kontrole dostepu (ACL) z klasa User, wiec teraz wszystko chodzi zgrabnie, a co najwazniejsze - dziala.

Adrian.
dragossani
Cytat
W ZF model jest, kontroler jest, ale widok jest mowiac krotko - nieporozumieniem. Programisci ZF albo wyszli z zalozenia ze i tak w aplikachach webowych prozentowana tresc to HTML, albo pomylilo im sie pojecie szablonow z widokiem.
Nic im się nie pomyliło. Po prostu uważają że kolejna warstwa jest zbędna bo php sam w sobie jest świetnym interpreterem szablonów. Ja się z nimi w całej rozciągłości zgadzam. Systemy szablonów z własną składnią to przerost formy - wystarczą wybrane mechanizmy szablonów (helpers, output filters, cache) i czysty php.

Z dokumentacji Zend Framework:
Cytat
Zend_View is a class for working with the "view" portion of the model-view-controller pattern. That is, it exists to help keep the view script separate from the model and controller scripts. It provides a system of helpers, output filters, and variable escaping.

Although php is itself a powerful template system, many developers feel it is too powerful or complex for their template designers.

Zend_View is template system agnostic; you may use php as your template language, or create instances of other template systems and manipulate them within your view script.

Przykład szablonu - jak dla mnie czytelne wystarczająco, nawet dla laika.
Seth
@dragossani: spagetti kod nie jest zbyt ciekawym rozwiązaniem. Mimo, że wydajnym.
W mojej ocenie łatwiej zarządzać i w ogóle odnaleźć się w systemie wzorców niż w przeplatanym kodzie HTML i php, gdzie osoby postronne mogą nie wiedzieć o przeznaczeniu wszystkich zmiennych.

Dodatkowo jest ryzyko, że ktoś wywoła np delete() na danym modelu. Wzorce minimalizują to ryzyko i dają możliwość pewnego ujednolicenia tej warstwy.

A co do templateów z użyciem ZF to ciekawe rozwiązanie zostało przedstawione na ZDZ:
http://devzone.zend.com/node/view/id/120

Kod z posta jednak nie jest kompletny bo brakuje mu przeciążenia metody _script() - ale w komentarzach jest ona podana.
dragossani
To trochę akademicki spór i mam wrażenie, że może być go trudno rozstrzygnąć bo argumenty są w dużej mierze natury estetycznej, a jak wiadomo o gustach się nie dyskutuje. :roll2:

O spagetti kodzie mówi się raczej w kontekście całkowitego ignorowania podziału na szablon i kod. Tutaj mamy natomiast do czynienia ze świadomym użyciem składni php w konstrukcji szablonu. Nie po to by szablon był czymś więcej niż jest lecz po to by nie wymyślać koła na nowo. Rozumiem odruchowy wstręt do samego pojawienia się php w szablonie (przecież po to jest szablon żeby kodu php tu nie było!) ale to moim zdaniem kompulsywna reakcja, a nie wynik chłodnej kalkulacji. Przecież chodzi nam o uzyskanie określonego efektu, pewnej logicznie wyodrębnionej struktury, a nie na wymyśleniu nowego meta-języka. Smarty i inne systemy szablonów to niestety kolejne warstwy meta-języka, kolejna składnia do opanowania. php użyte w szablonach nie musi skutkować bałaganem w strukturze aplikacji. Osoby postronne faktycznie nie muszą wiedzieć o przeznaczeniu wszystkich zmiennych i dlatego widok w Zend Framework dostaje zmienne tak jak w Smarty i twórca szablonu operuje tylko na nich. Składnia php przy takim zakresie jaki potrzebny jest przy tworzeniu szablonów jest nieskomplikowana i sprawdza się w tej roli.
Seth
W sumie racja. Wybor tych czy innych templateow glownie opiera sie o estetyke, ale nie mozna tez zapomniec, ze przeciez chocizaby smarty kompiluje kod do postaci php. Odchodzi nam wiec koniecznosc kazdorazowego otwierania i zamykania tagow php, a to oszczedza troche czasu przy projektowaniu wzorca.

No ale zgodze sie, ze jest to raczej kwestia gustow niz koniecznosci winksmiley.jpg
Sabistik
No to już jest obsługa sesji (w inkubatorze). Jak na razie 0 dokumentacji. Ktoś może już coś na niej działał?
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.