Zend_Session-AdvancedUsage.xml 25 KB

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