Zend_Session-AdvancedUsage.xml 26 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561
  1. <?xml version="1.0" encoding="UTF-8"?>
  2. <!-- EN-Revision: 17175 -->
  3. <!-- Reviewed: no -->
  4. <sect1 id="zend.session.advanced_usage">
  5. <title>Fortgeschrittene Benutzung</title>
  6. <para>
  7. Wärend die Beispiele für die Basisnutzung völlig akzeptierbar sind, in ihrem Weg Zend
  8. Framework Sessions zu Benutzen, ist auch die beste Praxis zu bedenken. Diese Sektion
  9. beschreibt die näheren Details von Session Handling und illustriert die fortgeschrittene
  10. Benutzung der <classname>Zend_Session</classname> Komponente.
  11. </para>
  12. <sect2 id="zend.session.advanced_usage.starting_a_session">
  13. <title>Starten einer Session</title>
  14. <para>
  15. Wenn man alle Anfragen einer Session durch <classname>Zend_Session</classname>
  16. bearbeitet haben will, muß die Session in der Bootstrap Datei gestartet werden:
  17. </para>
  18. <example id="zend.session.advanced_usage.starting_a_session.example">
  19. <title>Starten einer globalen Session</title>
  20. <programlisting language="php"><![CDATA[
  21. Zend_Session::start();
  22. ]]></programlisting>
  23. </example>
  24. <para>
  25. Durch das Starten der Session in der Bootstrap Datei verhindert man das die Session
  26. gestartet werden könnte nachdem die Header an den Browser gesendet wurde, was zu einer
  27. Ausnahme und möglicherweise zu einer fehlerhaften Seiten im Browser führen würde. Viele
  28. gehobenen Features benötigen zuerst <methodname>Zend_Session::start()</methodname>.
  29. (Mehr dazu später in den gehobenen Features)
  30. </para>
  31. <para>
  32. Es gibt vier Wege eine Session zustarten wenn <classname>Zend_Session</classname>
  33. verwendet wird. Zwei sind falsch.
  34. </para>
  35. <orderedlist>
  36. <listitem>
  37. <para>
  38. Falsch: PHP's <ulink
  39. url="http://www.php.net/manual/de/ref.session.php#ini.session.auto-start"><code>session.auto_start</code>
  40. Einstellung</ulink> darf nicht eingeschaltet werden. Wenn keine Möglichkeit
  41. besteht diese Einstellung in php.ini zu deaktivieren, und mod_php (oder
  42. ähnliches) verwendet wird, und die Einstellung schon in <code>php.ini</code>
  43. aktiviert ist, kann das folgende in der <code>.htaccess</code> Datei
  44. (normalerweise im HTML Dokumenten Basisverzeichnis) hinzugefügt werden:
  45. <programlisting language="httpd.conf"><![CDATA[
  46. php_value session.auto_start 0
  47. ]]></programlisting>
  48. </para>
  49. </listitem>
  50. <listitem>
  51. <para>
  52. Falsch: <acronym>PHP</acronym>'s <ulink
  53. url="http://www.php.net/session_start"><methodname>session_start()</methodname></ulink>
  54. Funktion darf nicht direkt verwendet werden. Wenn
  55. <methodname>session_start()</methodname> direkt, und anschließend
  56. <classname>Zend_Session_Namespace</classname> verwendet wird, wird von
  57. <methodname>Zend_Session::start()</methodname> eine Ausnahme geworfen ("session
  58. has already been started"). Wenn <methodname>Zend_Session::start()</methodname>
  59. ausgerufen wird, nachdem <classname>Zend_Session_Namespace</classname> verwendet
  60. wird oder <methodname>Zend_Session::start()</methodname> explizit verwendet
  61. wird, wird ein Fehler vom Level <constant>E_NOTICE</constant> erzeugt und der
  62. Aufruf wird ignoriert.
  63. </para>
  64. </listitem>
  65. <listitem>
  66. <para>
  67. Richtig: Verwenden von <methodname>Zend_Session::start()</methodname>. Wenn es
  68. gewünscht ist, das alle Anfragen eine Session haben und verwenden, sollte diese
  69. Funktion sehr früh, direkt und entscheidungslos in der Bootstrap Datei
  70. aufgerufen werden. Session haben einigen Overhead. Wenn einige Anfragen Sessions
  71. benötigen aber andere Anfragen keine Sessions verwenden, dann:
  72. </para>
  73. <itemizedlist mark="opencircle">
  74. <listitem>
  75. <para>
  76. Entscheidungslos, die <code>strict</code> Option auf
  77. <constant>TRUE</constant> setzen durch Verwendung von
  78. <methodname>Zend_Session::setOptions()</methodname> in der Bootstrap
  79. Datei.
  80. </para>
  81. </listitem>
  82. <listitem>
  83. <para>
  84. Aufruf von <methodname>Zend_Session::start()</methodname> nur für die
  85. Anfragen die eine Session verwenden müssen und vor jeglichen
  86. <classname>Zend_Session_Namespace</classname> initiiert werden.
  87. </para>
  88. </listitem>
  89. <listitem>
  90. <para>
  91. Normales verwenden von "<code>new Zend_Session_Namespace()</code>" wo es
  92. benötigt wird, aber sicherstellen das davor
  93. <methodname>Zend_Session::start()</methodname> ausgerufen wurde.
  94. </para>
  95. </listitem>
  96. </itemizedlist>
  97. <para>
  98. Die Option <code>strict</code> verhindert das <code>new
  99. Zend_Session_Namespace()</code> automatisch eine Session startet und dabei
  100. <methodname>Zend_Session::start()</methodname> verwendet. Deshalb hilft diese
  101. Option Anwendungs Entwicklern, sich für ein Design entscheiden zu können welches
  102. verhindert das für bestimmte Anfragen Sessions verwendet werden, da es eine
  103. Ausnahme verursachen würde wenn <classname>Zend_Session_Namespace</classname>
  104. instanziiert wird, bevor <methodname>Zend_Session::start()</methodname>
  105. aufgerufen wird. Entwickler sollten vorsichtig entscheiden welchen Einfluß die
  106. Verwendung von <methodname>Zend_Session::setOptions()</methodname> hat, da diese
  107. Optionen globale Seiteneffekte hat, in Folge der Korrespondenz der
  108. darunterliegenden Optionen für ext/session.
  109. </para>
  110. </listitem>
  111. <listitem>
  112. <para>
  113. Richtig: Einfach <code>new Zend_Session_Namespace()</code> instanzieren wo dies
  114. auch immer notwendig ist, und die darunterliegende <acronym>PHP</acronym>
  115. Session wird automatisch gestartet. Das bietet eine extrem simple Handhabung die
  116. in den meisten Situationen gut funktioniert. Trotzdem ist man dann dafür
  117. verantwortlich darauf zu schauen das das erste
  118. <code>new Zend_Session_Namespace()</code> passiert <emphasis>bevor</emphasis>
  119. irgendeine Ausgabe (z.B. <ulink
  120. url="http://www.php.net/headers_sent">HTTP headers</ulink> ) von
  121. <acronym>PHP</acronym> an den Client gesendet wird, wenn standardmäßige,
  122. Cookie-basierte Sessions verwendet werden (sehr empfehlenswert). Siehe <xref
  123. linkend="zend.session.global_session_management.headers_sent" /> für
  124. weitere Informationen.
  125. </para>
  126. </listitem>
  127. </orderedlist>
  128. </sect2>
  129. <sect2 id="zend.session.advanced_usage.locking">
  130. <title>Gesperrte Session Namensräume</title>
  131. <para>
  132. Session Namensräume können gesperrt werden um weitere Veränderungen der Daten in diesem
  133. Namensraum zu verhindern. Die Verwendung von <methodname>lock()</methodname> macht einen
  134. speziellen Namensraum nur-lesbar, <methodname>unLock()</methodname> macht einen
  135. nur-lesbaren Namensraum les- und schreibbar, und <methodname>isLocked()</methodname>
  136. prüft ob ein Namensraum vorher gesperrt wurde. Sperren sind flüchtig und bestehen nicht
  137. von einer Anfrage zur nächsten. Die Sperre des Namensraumes hat keinen Effekt auf
  138. Setz-Methoden von Objekten welche im Namensraum gespeichert sind, aber sie verhindert
  139. die Verwendung der Setz-Methoden des Namensraumes welche das gespeicherte Objekt direkt
  140. im Namensraum löschen oder ersetzen. Gleichwohl verhindert das Sperren von
  141. <classname>Zend_Session_Namespace</classname> Instanzen nicht die Verwendung von
  142. symbolischen Tabellen-Aliasen auf die gleichen Daten (siehe <ulink
  143. url="http://www.php.net/references">PHP references</ulink>).
  144. </para>
  145. <example id="zend.session.advanced_usage.locking.example.basic">
  146. <title>Sperren von Session Namensräumen</title>
  147. <programlisting language="php"><![CDATA[
  148. $userProfileNamespace = new Zend_Session_Namespace('userProfileNamespace');
  149. // marking session as read only locked
  150. $userProfileNamespace->lock();
  151. // unlocking read-only lock
  152. if ($userProfileNamespace->isLocked()) {
  153. $userProfileNamespace->unLock();
  154. }
  155. ]]></programlisting>
  156. </example>
  157. </sect2>
  158. <sect2 id="zend.session.advanced_usage.expiration">
  159. <title>Verfall von Namensräumen</title>
  160. <para>
  161. Limits können plaziert werden an der Lebensdauer von beidem, Namensräumen und
  162. individuellen Schlüsseln in Namensräumen. Normale Anwendungsfälle beinhalten das
  163. Durchlaufen von temporären Informationen zwischen Anfragen, und das vermindern der
  164. Aufdeckung von vielfältigen Sicherheitsrisiken durch das Entfernen des Zugangs zu
  165. potentiell sensitiven Informationen, manchmal nachdem Authentifizierung stettgefunden
  166. hat. Das Ende kann entweder auf abgelaufenen Sekunden oder der Anzahl von "Sprüngen"
  167. basieren, wobei ein Sprung für jede folgende Anfrage stattfindet.
  168. </para>
  169. <example id="zend.session.advanced_usage.expiration.example">
  170. <title>Beispiel für den Verfall</title>
  171. <programlisting language="php"><![CDATA[
  172. $s = new Zend_Session_Namespace('expireAll');
  173. $s->a = 'Apfel';
  174. $s->p = 'Pfirsich';
  175. $s->o = 'Orange';
  176. $s->setExpirationSeconds(5, 'a'); // Der Schlüssel "a" läuft in 5 Sekunden ab
  177. // Der komplette Namensraum läuft in 5 "Sprüngen"
  178. $s->setExpirationHops(5);
  179. $s->setExpirationSeconds(60);
  180. // Der "expireAll" Namensraum wird als "abgelaufen" markiert
  181. // sobald der erste Aufruf empfangen wurde und 60 Sekunden
  182. // vergangen sind, oder in 5 Sprüngen, was auch immer zuerst stattfindet
  183. ]]></programlisting>
  184. </example>
  185. <para>
  186. Wenn mit Daten einer Session gearbeitet wird, die in der aktuellen Anfrage ablaufen,
  187. sollte Vorsicht beim Empfangen dieser Daten gehalten werden. Auch wenn diese Daten durch
  188. Referenz zurückgegeben werden, wird die Änderung derselben, diese Daten nicht über diese
  189. Abfrage hinweg gültig machen. Um die Zeit für das Ablaufen zu "resetieren", müssen die
  190. Daten in eine temporäre Variable geholt werden, diese im Namensraum entfernt und
  191. anschliessend der entsprechende Schlüssel wieder gesetzt werden.
  192. </para>
  193. </sect2>
  194. <sect2 id="zend.session.advanced_usage.controllers">
  195. <title>Kapseln von Sessions und Controller</title>
  196. <para>
  197. Namensräume können auch verwendet werden um den Zugriff auf Sessions durch Controller
  198. zu seperieren um Variablen vor Kontaminierung zu schützen. Zum Beispiel könnte ein
  199. Authentifizierungs Controller seine Session Daten von allen anderen Controllern separat
  200. halten um notwendigen Sicherheiten zu entsprechen.
  201. </para>
  202. <example id="zend.session.advanced_usage.controllers.example">
  203. <title>Session Namensräume für Controller mit automatischem Verfall</title>
  204. <para>
  205. Der folgende Code ist Teil eines Controllers der die Test Frage anzeigt und eine
  206. boolsche Variable initialisiert die anzeigt ob eine geschickte Antwort zur Test
  207. Frage akzeptiert werden sollte oder nicht. In diesem Fall wird dem Benutzer der
  208. Anwendung 300 Sekunden Zeit gegeben die angezeigte Frage zu beantworten.
  209. </para>
  210. <programlisting language="php"><![CDATA[
  211. // ...
  212. // Im Frage-View Controller
  213. $testSpace = new Zend_Session_Namespace('testSpace');
  214. $testSpace->setExpirationSeconds(300, 'accept_answer');
  215. // Nur diese Variable ablaufen lassen
  216. $testSpace->accept_answer = true;
  217. //...
  218. ]]></programlisting>
  219. <para>
  220. Danach bestimmt der Controller der die Antworten für die Test Fragen bearbeitet ob
  221. eine Antwort akzeptiert wird oder nach basierend darauf ob der Benutzer die Antwort
  222. in der erlaubten Zeit übermittelt hat:
  223. </para>
  224. <programlisting language="php"><![CDATA[
  225. // ...
  226. // Im Frage-Prozess Controller
  227. $testSpace = new Zend_Session_Namespace('testSpace');
  228. if ($testSpace->accept_answer === true) {
  229. // innerhalb der Zeit
  230. }
  231. else {
  232. // nicht innerhalb der Zeit
  233. }
  234. // ...
  235. ]]></programlisting>
  236. </example>
  237. </sect2>
  238. <sect2 id="zend.session.advanced_usage.single_instance">
  239. <title>Mehrfache Instanzen pro Namensraum verhindern</title>
  240. <para>
  241. Obwohl <link linkend="zend.session.advanced_usage.locking">session locking</link> einen
  242. guten Grad von Schutz gegen unerlaubte Verwendung von Session Daten in einem Namensraum
  243. bietet, bietet <classname>Zend_Session_Namespace</classname> auch die Fähigkeit die
  244. Erzeugung von mehreren Instanzen zu verhindern die zu einem einzelnen Namensraum
  245. korrespondieren.
  246. </para>
  247. <para>
  248. Um dieses Verhalten einzuschalten, muß <constant>TRUE</constant> als zweites Argument im
  249. Konstruktor angegeben werden wenn die letzte erlaubt Instanz von
  250. <classname>Zend_Session_Namespace</classname> erzeugt wurde. Jeder weitere Versuch den
  251. selben Namensraum zu instanzieren wird in einer geworfenen Ausnahme resultieren.
  252. </para>
  253. <example id="zend.session.advanced_usage.single_instance.example">
  254. <title>Zugriff auf Session Namensräume auf eine einzelne Instanz limitieren</title>
  255. <programlisting language="php"><![CDATA[
  256. // Eine Instanz eines Namensraumes erstellen
  257. $authSpaceAccessor1 = new Zend_Session_Namespace('Zend_Auth');
  258. // Eine weitere Instanz des selben Namensraumes erstellen,
  259. // aber weitere Instanzen verbieten
  260. $authSpaceAccessor2 = new Zend_Session_Namespace('Zend_Auth', true);
  261. // Eine Referenz erstellen ist immer noch möglich
  262. $authSpaceAccessor3 = $authSpaceAccessor2;
  263. $authSpaceAccessor1->foo = 'bar';
  264. assert($authSpaceAccessor2->foo, 'bar');
  265. try {
  266. $aNamespaceObject = new Zend_Session_Namespace('Zend_Auth');
  267. } catch (Zend_Session_Exception $e) {
  268. echo 'Dieser Namensraum kann nicht instanziert werden da ' .
  269. '$authSpaceAccessor2 erstellt wurde\n';
  270. }
  271. ]]></programlisting>
  272. </example>
  273. <para>
  274. Der zweite Parameter oben im Konstruktor sagt
  275. <classname>Zend_Session_Namespace</classname> das alle zukünftigen Instanzen mit dem
  276. <classname>Zend_Auth</classname> Namensraum nicht erlaubt sind. Der Versuch solche
  277. Instanzen zu erstellen verursacht eine Ausnahme die vom Konstruktor geworfen wird. Der
  278. Entwickler wird darauf aufmerksam gemacht eine Referenz zu einer Instanz des Objektes
  279. irgendwo zu speichern (<varname>$authSpaceAccessor1</varname>,
  280. <varname>$authSpaceAccessor2</varname>, oder <varname>$authSpaceAccessor3</varname> im
  281. obigen Beispiel), wenn der Zugriff auf den Namensraum der Session zu einer späteren Zeit
  282. wärend des selben Requests benötigt wird. Zum Beispiel, könnte ein Entwickler die
  283. Referenz in einer statischen Variable speichern, die Referenz zu einer <ulink
  284. url="http://www.martinfowler.com/eaaCatalog/registry.html">Registry</ulink>
  285. hinzufügen (siehe <xref linkend="zend.registry" />), oder diese andernfalls für andere
  286. Methoden verfügbar zu machen die Zugriff auf den Namensraum der Session benötigen.
  287. </para>
  288. </sect2>
  289. <sect2 id="zend.session.advanced_usage.arrays">
  290. <title>Arbeiten mit Arrays</title>
  291. <para>
  292. Durch die Vergangenheit der Implmentationen der Magischen Methoden in
  293. <acronym>PHP</acronym>, wird das Ändern von Arrays innerhalb eines Namensraumes nicht
  294. unter <acronym>PHP</acronym> Versionen vor 5.2.1 funktionieren. Wenn nur mit
  295. <acronym>PHP</acronym> 5.2.1 oder neuer gearbeitet wird, kann <link
  296. linkend="zend.session.advanced_usage.objects">zum nächsten Kapitel gesprungen</link>
  297. werden.
  298. </para>
  299. <example id="zend.session.advanced_usage.arrays.example.modifying">
  300. <title>Array Daten innerhalb eines Session Namensraumes verändern</title>
  301. <para>
  302. Das folgende illustriert wie das Problem reproduziert werden kann:
  303. </para>
  304. <programlisting language="php"><![CDATA[
  305. $sessionNamespace = new Zend_Session_Namespace();
  306. $sessionNamespace->array = array();
  307. // wird nicht wie gewünscht funktionieren vor PHP 5.2.1
  308. $sessionNamespace->array['testKey'] = 1;
  309. echo $sessionNamespace->array['testKey'];
  310. ]]></programlisting>
  311. </example>
  312. <example id="zend.session.advanced_usage.arrays.example.building_prior">
  313. <title>Arrays erstellen bevor es Session Speicher gab</title>
  314. <para>
  315. Wenn möglich, sollte das Problem vermieden werden indem Array nur dann im Session
  316. Namensraum gespeichert werden nachdem alle gewünschten Arraywerte gesetzt wurden.
  317. </para>
  318. <programlisting language="php"><![CDATA[
  319. $sessionNamespace = new Zend_Session_Namespace('Foo');
  320. $sessionNamespace->array = array('a', 'b', 'c');
  321. ]]></programlisting>
  322. </example>
  323. <para>
  324. Wenn eine betroffene Version von <acronym>PHP</acronym> verwendet wird and ein Array
  325. modifiziert werden soll nachdem es mit einem Schlüssel für den Session Namensraum
  326. verbunden wurde, kann einer oder beide der folgenden Workarounds verwendet werden.
  327. </para>
  328. <example id="zend.session.advanced_usage.arrays.example.workaround.reassign">
  329. <title>Workaround: Ein geändertes Array neu Verbinden</title>
  330. <para>
  331. Im folgenden Code wird eine Kopie des gespeicherten Array erstellt, geändert und
  332. wieder dem Platz von dem die Kopie erstellt wurde zugeordnet wobei das originale
  333. Array überschrieben wird.
  334. </para>
  335. <programlisting language="php"><![CDATA[
  336. $sessionNamespace = new Zend_Session_Namespace();
  337. // Das ursprüngliche Array hinzufügen
  338. $sessionNamespace->array = array('tree' => 'apple');
  339. // Eine Kopie des Arrays erstellen
  340. $tmp = $sessionNamespace->array;
  341. // Die Kopie des Arrays ändern
  342. $tmp['fruit'] = 'peach';
  343. // Die Kopie des Arrays wieder mit dem Namensraum der Session verknüpfen
  344. $sessionNamespace->array = $tmp;
  345. echo $sessionNamespace->array['fruit']; // gibt "peach" aus
  346. ]]></programlisting>
  347. </example>
  348. <example id="zend.session.advanced_usage.arrays.example.workaround.reference">
  349. <title>Workaround: Array das Referenz enthält speichern</title>
  350. <para>
  351. Alternativ, kann ein Array gespeichert werden das eine Referenz zum gewünschten
  352. Array enthält, die auf dieses dann indirekt zugegriffen werden.
  353. </para>
  354. <programlisting language="php"><![CDATA[
  355. $myNamespace = new Zend_Session_Namespace('myNamespace');
  356. $a = array(1, 2, 3);
  357. $myNamespace->someArray = array( &$a );
  358. $a['foo'] = 'bar';
  359. echo $myNamespace->someArray['foo']; // gibt "bar" aus
  360. ]]></programlisting>
  361. </example>
  362. </sect2>
  363. <sect2 id="zend.session.advanced_usage.objects">
  364. <title>Sessions mit Objekten verwenden</title>
  365. <para>
  366. Wenn Objekte in einer <acronym>PHP</acronym> Session fixiert werden sollen, muß bedacht
  367. werden das diese für das Speichern <ulink
  368. url="http://www.php.net/manual/de/language.oop.serialization.php">serialisiert</ulink>
  369. werden. Deshalb muß jedes Objekt das in einer <acronym>PHP</acronym> Session verewigt
  370. wurde deserialisiert werden nachdem es vom Speicher empfangen wurde. Das impliziert das
  371. der Entwickler sicherstellen muß das die Klassen für das verewigte Objekt definiert
  372. werden müssen bevor das Objekt vom Session Speicher deserialisiert wird. Wenn die
  373. Klasse eines unserialisierten Objektes nicht definiert wurde, wird es eine Instand von
  374. <code>stdClass</code>.
  375. </para>
  376. </sect2>
  377. <sect2 id="zend.session.advanced_usage.testing">
  378. <title>Verwenden von Sessions mit Unit Tests</title>
  379. <para>
  380. Zend Framework vertraut auf PHPUnit um das Testen von sich selbst zu ermöglichen. Viele
  381. Entwickler erweitern die existierende Sammlung von Unit Tests um den Code in deren
  382. Anwendungen anzudecken. Die Ausnahme "<emphasis>Zend_Session ist aktuell als nur-lesbar
  383. markiert</emphasis>" wird geworfen wärend Unit Tests durchgeführt werden, wenn
  384. irgendeine schreibende Methode verwendet wird nachdem Ende der Session. Trotzdem
  385. benötigen Unit Tests die <classname>Zend_Session</classname> verwenden besondere
  386. Aufmerksamkeit weil das Schließen (<methodname>Zend_Session::writeClose()</methodname>)
  387. oder Zerstören einer Session (<methodname>Zend_Session::destroy()</methodname>) weitere
  388. Änderungen oder Rücknahmen von Schlüsseln in jeder Instanz von
  389. <classname>Zend_Session_Namespace</classname> verhindert. Dieses Verhalten ist ein
  390. direktes Resultat des darunterliegenden ext/session Mechanismus und
  391. <acronym>PHP</acronym>'s <methodname>session_destroy()</methodname> und
  392. <methodname>session_write_close()</methodname> welche keinen "rückgängig machen"
  393. Mechanismus unterstützen um Setup/Teardown innerhalb der Unit Tests zu unterstützen.
  394. </para>
  395. <para>
  396. Um das Umzuarbeiten, siehe den Unit Test
  397. <methodname>testSetExpirationSeconds()</methodname> in <code>SessionTest.php</code> und
  398. <code>SessionTestHelper.php</code>, beide im <code>tests/Zend/Session</code>
  399. Verzeichnis, welche <acronym>PHP</acronym>'s <methodname>exec()</methodname> verwenden
  400. um einen eigenständigen Prozess zu starten. Der neue Prozess simuliert eine zweite
  401. Anfrage eines Browsers, viel genauer. Der separate Prozess beginnt mit einer "reinen"
  402. Session, genauso wie jede <acronym>PHP</acronym> Skript Ausführung für eine Web Anfrage.
  403. Auch jede Änderung in <varname>$_SESSION</varname> welche im aufrufenden Prozess gemacht
  404. wurde, ist im Kind-Prozess verfügbar, ermöglicht wenn der Elternprozess die Session
  405. beendet hat, bevor <methodname>exec()</methodname> verwendet wird.
  406. </para>
  407. <example id="zend.session.advanced_usage.testing.example">
  408. <title>PHPUnit Test Code der auf Zend_Session beruht</title>
  409. <programlisting language="php"><![CDATA[
  410. // testen von setExpirationSeconds()
  411. $script = 'SessionTestHelper.php';
  412. $s = new Zend_Session_Namespace('space');
  413. $s->a = 'apple';
  414. $s->o = 'orange';
  415. $s->setExpirationSeconds(5);
  416. Zend_Session::regenerateId();
  417. $id = Zend_Session::getId();
  418. // Session freigeben damit der untere Prozess Sie verwenden kann
  419. session_write_close();
  420. sleep(4); // nicht lange genug damit die Dinge ablaufen
  421. exec($script . "expireAll $id expireAll", $result);
  422. $result = $this->sortResult($result);
  423. $expect = ';a === apfel;o === orange;p === pfirsich';
  424. $this->assertTrue($result === $expect,
  425. "Iterierung durch standard Zend_Session Namensraum fehlgeschlagen; " .
  426. "erwartet result === '$expect', aber '$result' bekommen");
  427. sleep(2); // lange genug damit die Dinge ablaufen (insgesamt 6 Sekunden
  428. // warten, aber nach 5 Sekunden abgelaufen)
  429. exec($script . "expireAll $id expireAll", $result);
  430. $result = array_pop($result);
  431. $this->assertTrue($result === '',
  432. "Iterierung durch standard Zend_Session Namensraum fehlgeschlagen; " .
  433. "erwartet result === '', aber '$result' bekommen)");
  434. session_start(); // wiederherstellen der vorher eingefrorenen Session
  435. // Das könnte in einen separaten Test abgeteilt werden, aber aktuell, wenn
  436. // irgendwas vom darüberleigenden Test den darunterliegenden Test
  437. // kontaminiert, ist das auch ein Fehler den wir wissen wollen.
  438. $s = new Zend_Session_Namespace('expireGuava');
  439. $s->setExpirationSeconds(5, 'g'); // Versuch nur einen Schlüssel im
  440. // Namensraum ablaufen zu lassen
  441. $s->g = 'guava';
  442. $s->p = 'peach';
  443. $s->p = 'plum';
  444. // Session auflösen damit der untere Prozess sie verwenden kann
  445. session_write_close();
  446. sleep(6); // Nicht lange genug damit die Dinge ablaufen können
  447. exec($script . "expireAll $id expireGuava", $result);
  448. $result = $this->sortResult($result);
  449. session_start(); // Die bestimmte Session wiederherstellen
  450. $this->assertTrue($result === ';p === plum',
  451. "Iterierung durch benannte Zend_Session Namensräume " .
  452. "fehlgeschlaten (result=$result)");
  453. ]]></programlisting>
  454. </example>
  455. </sect2>
  456. </sect1>