Zend_Session-AdvancedUsage.xml 25 KB

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