| 123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438 |
- <?xml version="1.0" encoding="UTF-8"?>
- <!-- EN-Revision: 24249 -->
- <!-- Reviewed: 21826 -->
- <sect1 id="zend.controller.request">
- <title>Das Request-Objekt</title>
- <sect2 id="zend.controller.request.introduction">
- <title>Einführung</title>
- <para>
- Das Request-Objekt ist eine einfaches Werteobjekt, das zwischen
- <classname>Zend_Controller_Front</classname> und den Router, Dispatcher und Controller
- Klassen übergeben wird. Es enthält sowohl die Definition des Controllers, der Aktion und
- der Parameter, die an die Aktion übergeben werden sollen, als auch den Rest der
- Anfrageumgebung, sei es <acronym>HTTP</acronym>, <acronym>CLI</acronym> oder
- <acronym>PHP</acronym>-GTK.
- </para>
- <itemizedlist>
- <listitem>
- <para>
- Auf den Modulnamen kann über <methodname>getModuleName()</methodname> und
- <methodname>setModuleName()</methodname> zugegriffen werden.
- </para>
- </listitem>
- <listitem>
- <para>
- Auf den Controller-Namen kann über <methodname>getControllerName()</methodname>
- und <methodname>setControllerName()</methodname> zugegriffen werden.
- </para>
- </listitem>
- <listitem>
- <para>
- Auf den Namen der Aktion, die in diesem Controller aufgerufen wird, kann über
- <methodname>getActionName()</methodname> und
- <methodname>setActionName()</methodname> zugegriffen werden.
- </para>
- </listitem>
- <listitem>
- <para>
- Parameter, die von der Aktion ansprechbar sind, bestehen aus einem assoziativen
- Array mit Paaren von Schlüsseln und Werten, auf die komplett per
- <methodname>getParams()</methodname> und <methodname>setParams()</methodname>
- oder einzeln per <methodname>getParam()</methodname> und
- <methodname>setParam()</methodname> zugegriffen werden kann.
- </para>
- </listitem>
- </itemizedlist>
- <para>
- Abhängig vom Typ der Anfrage können auch weitere Methoden verfügbar sein. Das
- verwendete Standard-Request-Objekt <classname>Zend_Controller_Request_Http</classname>
- stellt z.B. Methoden zum Abfragen der Request-<acronym>URI</acronym>, Pfadinformationen,
- den Parametern <varname>$_GET</varname> und <varname>$_POST</varname> usw. bereit.
- </para>
- <para>
- Das Request-Objekt wird an den FrontController übergeben oder, wenn keines bereit
- gestellt wurde, am Anfang des Dispatcher-Prozesses instanziert, bevor das Routing
- beginnt. Es wird an jedes Objekt in der Dispatcherkette übergeben.
- </para>
- <para>
- Zusätzlich ist das Request-Objekt besonders beim Testen sehr nützlich. Der Entwickler
- kann die Anfrageumgebung von Hand erstellen, inklusive Controller, Aktion, Parameter,
- <acronym>URI</acronym> usw. und das Request-Objekt an den Front Controller übergeben, um
- den Ablauf der Applikation zu testen. Zusammen mit dem
- <link linkend="zend.controller.response">Response-Objekt</link> sind durchdachte und
- genaue UnitTests für eine <acronym>MVC</acronym>-Applikation möglich.
- </para>
- </sect2>
- <sect2 id="zend.controller.request.http">
- <title>HTTP-Anfragen</title>
- <sect3 id="zend.controller.request.http.dataacess">
- <title>Auf Request-Daten zugreifen</title>
- <para>
- <classname>Zend_Controller_Request_Http</classname> kapselt den Zugriff auf
- relevante Werte wie Schlüsselname und Wert für Controller und Action, Variablen des
- Routers und alle zusätzlichen Parameter, die aus der <acronym>URI</acronym>
- ermittelt wurden. Es erlaubt zusätzlich den Zugriff auf superglobale Werte als
- öffentliche Eigenschaften und verwaltet die aktuelle Basis-<acronym>URL</acronym>
- und Request-<acronym>URI</acronym>. Superglobale Werte können in einem
- Request-Objekt nicht gesetzt werden, stattdessen verwendet man die
- Methoden <methodname>setParam()</methodname> und <methodname>getParam()</methodname>
- um Benutzerparameter zu setzen oder zu erhalten.
- </para>
- <note>
- <title>Superglobale Daten</title>
- <para>
- Beim Zugriff auf superglobale Daten über die öffentlichen Eigenschaften von
- <classname>Zend_Controller_Request_Http</classname> ist es notwendig, darauf zu
- achten, dass der Eigenschaftsname (der superglobale Arrayschlüssel) einem
- superglobalen Wert in einer bestimmten Reihenfolge entspricht: 1.
- <constant>GET</constant>, 2. <constant>POST</constant>, 3.
- <constant>COOKIE</constant>, 4. <constant>SERVER</constant>, 5.
- <constant>ENV</constant>.
- </para>
- </note>
- <para>
- Auf spezifische superglobale Werte kann alternativ über eine öffentliche Methode
- zugegriffen werden. Zum Beispiel kann auf den unverarbeiteten Wert von
- <varname>$_POST['user']</varname> durch Aufruf der
- Methode <methodname>getPost('user')</methodname> des Request-Objekts zugegriffen
- werden. Diese beinhalten <methodname>getQuery()</methodname>, um
- <varname>$_GET</varname>-Elemente zu erhalten und
- <methodname>getHeader()</methodname>, um Request-Header zu erhalten.
- </para>
- <note>
- <title>GET- und POST-Daten</title>
- <para>
- Es ist Vorsicht geboten, wenn auf Daten eines Anfrageobjekts zugegriffen wird,
- da diese in keiner Weise gefiltert werden. Der Router und Dispatcher prüfen und
- filtern Daten für die Verwendung innerhalb ihrer Aufgabe, lassen diese Daten
- aber unangetastet im Anfrageobjekt.
- </para>
- </note>
- <note>
- <title>Abfrage der unverarbeitetet ("raw") POST-Daten</title>
- <para>
- Ab 1.5.0 können auch die rohen POST-Daten über die
- Methode <methodname>getRawBody()</methodname> erhalten werden. Diese Methode
- gibt <constant>FALSE</constant> zurück, wenn keine Daten auf diesem Weg
- übermittelt wurden, andernfalls den kompletten Inhalt von POST.
- </para>
- <para>
- Das ist grundsätzlich sinnvoll, um Inhalt zu akzeptieren, wenn eine RESTvolle
- <acronym>MVC</acronym>-Anwendung entwickelt wird.
- </para>
- </note>
- <para>
- Im Anfrageobjekt können auch Benutzerparameter durch Verwendung von
- <methodname>setParam()</methodname> gesetzt werden und später durch
- verwenden von <methodname>getParam()</methodname> zurückgegeben werden. Der Router
- verwendet diese Funktionalität, um passende Parameter in der
- Anfrage-<acronym>URI</acronym> im Anfrageobjekt zu setzen.
- </para>
- <note>
- <title>getParam() empfängt mehr als Benutzerparameter</title>
- <para>
- Um einfach seinen Job zu erledigen, sammelt <methodname>getParam()</methodname>
- Daten von verschiedenen Quellen. Je nach Priorität enthalten diese:
- Benutzerparameter, die über <methodname>setParam()</methodname> gesetzt wurden,
- <constant>GET</constant>-Parameter und letztendlich
- <constant>POST</constant>-Parameter. Seien Sie sich dieser Tatsache bewusst,
- wenn Sie Daten mit dieser Methode holen.
- </para>
- <para>
- Wenn man nur Parameter erhalten will, die vorher mit
- <methodname>setParam()</methodname> gesetzt wurden, muß
- <methodname>getUserParam()</methodname> verwendet werden.
- </para>
- <para>
- Zusätzlich kann seit 1.5.0 abgesichert werden, welche Parameterquellen durchsucht
- werden. <methodname>setParamSources()</methodname> erlaubt es, ein leeres Array
- anzugeben oder ein Array mit einem oder mehreren Werten von '_GET' oder
- '_POST' um zu zeigen, welche Parameterquellen erlaubt sind (standardmäßig sind
- beide erlaubt); wenn der Zugriff nur auf '_GET' beschränkt werden soll, muß
- <methodname>setParamSources(array('_GET'))</methodname> angegeben werden.
- </para>
- </note>
- <note>
- <title>Apache Quirks</title>
- <para>
- Wenn der 404-Handler des Apache verwendet wird, um eingehende Anfragen an den
- FrontController zu übergeben, oder ein PT Flag mit Rewrite Regeln verwendet wird,
- enthält <varname>$_SERVER['REDIRECT_URL']</varname> die <acronym>URI</acronym>,
- die benötigt wird, nicht <varname>$_SERVER['REQUEST_URI']</varname>. Wenn so ein
- Setup verwendet wird und man ungültige Routen erhält, sollte man stattdessen die
- Klasse <classname>Zend_Controller_Request_Apache404</classname> statt der
- Standard-<acronym>HTTP</acronym>-Klasse für das Anfrageobjekt verwenden:
- </para>
- <programlisting language="php"><![CDATA[
- $request = new Zend_Controller_Request_Apache404();
- $front->setRequest($request);
- ]]></programlisting>
- <para>
- Diese Klasse erweitert die Klasse
- <classname>Zend_Controller_Request_Http</classname> und modifiziert einfach die
- automatische Erkennung der Anfrage-<acronym>URI</acronym>. Sie kann als
- einfache Ersetzung verwendet werden.
- </para>
- </note>
- </sect3>
- <sect3 id="zend.controller.request.http.baseurl">
- <title>Basis-Url und Unterverzeichnisse</title>
- <para>
- <classname>Zend_Controller_Request_Http</classname> erlaubt, dass
- <classname>Zend_Controller_Router_Rewrite</classname> in einem Unterverzeichnis
- verwendet werden kann. <classname>Zend_Controller_Request_Http</classname> versucht,
- die Basis-<acronym>URL</acronym> automatisch zu erkennen und entsprechend zu setzen.
- </para>
- <para>
- Wenn man zum Beispiel seine <filename>index.php</filename> in einem
- Webserverunterverzeichnis mit Namen <filename>/projects/myapp/index.php</filename>
- verwendet, sollte die Basis-<acronym>URL</acronym> (die Rewrite-Basis) auf
- <filename>/projects/myapp</filename> gesetzt werden. Dieser String wird dann vom
- Anfang des Pfades entfernt, bevor irgendwelche Routingtreffer ermittelt werden.
- Dies befreit einen davon, es am Anfang jeder Route setzen zu müssen. Eine Route
- <command>'user/:username'</command> passt auf <acronym>URI</acronym>s wie
- <filename>http://localhost/projects/myapp/user/martel</filename> und
- <filename>http://example.com/user/martel</filename>.
- </para>
- <note>
- <title>URL-Erkennung beachtet Groß- und Kleinschreibung</title>
- <para>
- Die automatische Erkennung der Basis-<acronym>URL</acronym> beachtet die Groß-
- und Kleinschreibung, weshalb man sicherstellen sollte, dass die
- <acronym>URL</acronym> einem Unterverzeichnis im Dateisystem entspricht (sogar
- auf einem Windows-Rechner). Andernfalls wird eine Ausnahme geworfen.
- </para>
- </note>
- <para>
- Sollte die Basis-<acronym>URL</acronym> falsch erkannt werden, kann man diese auch
- mit einem eigenen Pfad mit Hilfe der Methode <methodname>setBaseUrl()</methodname>
- der Klasse <classname>Zend_Controller_Request_Http</classname> oder der
- Klasse <classname>Zend_Controller_Front</classname> überschreiben. Die einfachste
- Methode ist die von <classname>Zend_Controller_Front</classname>, welche es an das
- Request-Objekt weiterleitet. Nun Beispiel, um eine eigene
- Basis-<acronym>URL</acronym> zu setzen:
- </para>
- <programlisting language="php"><![CDATA[
- /**
- * Dispatch-Anfrage mit einer kundenbasierenden URL mit Zend_Controller_Front.
- */
- $router = new Zend_Controller_Router_Rewrite();
- $controller = Zend_Controller_Front::getInstance();
- $controller->setControllerDirectory('./application/controllers')
- ->setRouter($router)
- ->setBaseUrl('/projects/myapp'); // Setze die Basis-URL!
- $response = $controller->dispatch();
- ]]></programlisting>
- </sect3>
- <sect3 id="zend.controller.request.http.method">
- <title>Erkennen der Anfragemethode</title>
- <para>
- <methodname>getMethod()</methodname> erlaubt es die
- <acronym>HTTP</acronym>-Anfragemethode zu erkennen, die verwendet wurde, um die
- aktuelle Ressource anzufragen.
- Zusätzlich existiert eine Vielzahl von Methoden, die es erlauben, boolsche Antworten
- zu erhalten, wenn gefragt wird, ob ein spezieller Typ von Anfrage durchgeführt wurde:
- </para>
- <itemizedlist>
- <listitem><para><methodname>isGet()</methodname></para></listitem>
- <listitem><para><methodname>isPost()</methodname></para></listitem>
- <listitem><para><methodname>isPut()</methodname></para></listitem>
- <listitem><para><methodname>isDelete()</methodname></para></listitem>
- <listitem><para><methodname>isHead()</methodname></para></listitem>
- <listitem><para><methodname>isOptions()</methodname></para></listitem>
- </itemizedlist>
- <para>
- Der grundsätzliche Verwendungszweck hierfür ist die Erstellung von RESTvollen
- <acronym>MVC</acronym>-Architekturen.
- </para>
- </sect3>
- <sect3 id="zend.controller.request.http.ajax">
- <title>Erkennen von AJAX-Anfragen</title>
- <para>
- <classname>Zend_Controller_Request_Http</classname> hat eine rudimentäre Methode für
- die Erkennung von <acronym>AJAX</acronym>-Anfragen:
- <methodname>isXmlHttpRequest()</methodname>. Diese Methode sucht nach einem
- <acronym>HTTP</acronym>-Anfrageheader <emphasis>X-Requested-With</emphasis> mit dem
- Wert 'XMLHttpRequest'; wenn er gefunden wird, gibt er <constant>TRUE</constant>
- zurück.
- </para>
- <para>
- Aktuell wird dieser Header standardmäßig mit den folgenden JS-Bibliotheken
- geschickt:
- </para>
- <itemizedlist>
- <listitem>
- <para>
- Prototype und Scriptaculous (und von Prototype abgeleitete Bibliotheken)
- </para>
- </listitem>
- <listitem><para>Yahoo! UI Library</para></listitem>
- <listitem><para>jQuery</para></listitem>
- <listitem><para>MochiKit</para></listitem>
- </itemizedlist>
- <para>
- Die meisten <acronym>AJAX</acronym>-Bibliotheken erlauben das Senden von eigenen
- <acronym>HTTP</acronym>-Anfrageheadern; wenn die eigene Bibliothek diesen Header
- nicht sendet, muß dieser einfach zum Anfrageheader hinzugefügt werden um
- sicherzustellen, dass die Methode <methodname>isXmlHttpRequest()</methodname>
- funktioniert.
- </para>
- </sect3>
- </sect2>
- <sect2 id="zend.controller.request.subclassing">
- <title>Vererben des Anfrageobjekts</title>
- <para>
- Die Basisanfrageklasse, die für alle Anfrageobjekte verwendet wird, ist die abstrakte
- Klasse <classname>Zend_Controller_Request_Abstract</classname>. Sie ist sehr
- grundsätzlich und definiert die folgenden Methoden:
- </para>
- <programlisting language="php"><![CDATA[
- abstract class Zend_Controller_Request_Abstract
- {
- /**
- * @return string
- */
- public function getControllerName();
- /**
- * @param string $value
- * @return self
- */
- public function setControllerName($value);
- /**
- * @return string
- */
- public function getActionName();
- /**
- * @param string $value
- * @return self
- */
- public function setActionName($value);
- /**
- * @return string
- */
- public function getControllerKey();
- /**
- * @param string $key
- * @return self
- */
- public function setControllerKey($key);
- /**
- * @return string
- */
- public function getActionKey();
- /**
- * @param string $key
- * @return self
- */
- public function setActionKey($key);
- /**
- * @param string $key
- * @return mixed
- */
- public function getParam($key);
- /**
- * @param string $key
- * @param mixed $value
- * @return self
- */
- public function setParam($key, $value);
- /**
- * @return array
- */
- public function getParams();
- /**
- * @param array $array
- * @return self
- */
- public function setParams(array $array);
- /**
- * @param boolean $flag
- * @return self
- */
- public function setDispatched($flag = true);
- /**
- * @return boolean
- */
- public function isDispatched();
- }
- ]]></programlisting>
- <para>
- Das Anfrageobjekt ist ein Behälter für die Anfrageumgebung. Die Controller-Kette muß
- wirklich nur wissen, wie der Controller, die Aktion, die optionalen Parameter und der
- Dispatched-Status gesetzt und empfangen werden können. Standardmäßig durchsucht das
- Anfrageobjekt die eigenen Parameter, indem es die Schlüssel für Controller oder Aktion
- verwendet um den Controller und die Aktion zu ermitteln.
- </para>
- <para>
- Erweiteren Sie diese Klasse oder eine ihrer Derivate, wenn die Anfrageklasse mit einer
- speziellen Umgebung interagieren soll, um Daten für die obigen Aufgaben zu erhalten.
- Beispiele beinhalten <link linkend="zend.controller.request.http">die
- <acronym>HTTP</acronym>-Umgebung</link>, eine <acronym>CLI</acronym>-Umgebung, oder
- eine <acronym>PHP</acronym>-GTK-Umgebung.
- </para>
- </sect2>
- </sect1>
|