| 123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458 |
- <?xml version="1.0" encoding="UTF-8"?>
- <!-- Reviewed: no -->
- <sect1 id="zend.controller.request">
- <title>The Request Object</title>
- <sect2 id="zend.controller.request.introduction">
- <title>Introduction</title>
- <para>
- The request object is a simple value object that is passed between
- <classname>Zend_Controller_Front</classname> and the router, dispatcher, and
- controller classes. It packages the names of the requested module,
- controller, action, and optional parameters, as well as the rest of
- the request environment, be it <acronym>HTTP</acronym>, the <acronym>CLI</acronym>, or
- <acronym>PHP</acronym>-GTK.
- </para>
- <itemizedlist>
- <listitem>
- <para>
- The module name is accessed by <methodname>getModuleName()</methodname> and
- <methodname>setModuleName()</methodname>.
- </para>
- </listitem>
- <listitem>
- <para>
- The controller name is accessed by <methodname>getControllerName()</methodname>
- and <methodname>setControllerName()</methodname>.
- </para>
- </listitem>
- <listitem>
- <para>
- The name of the action to call within that controller is
- accessed by <methodname>getActionName()</methodname> and
- <methodname>setActionName()</methodname>.
- </para>
- </listitem>
- <listitem>
- <para>
- Parameters to be accessible by the action are an associative array
- of key and value pairs that are retrieved by
- <methodname>getParams()</methodname> and set with
- <methodname>setParams()</methodname>, or individually by
- <methodname>getParam()</methodname> and <methodname>setParam()</methodname>.
- </para>
- </listitem>
- </itemizedlist>
- <para>
- Based on the type of request, there may be more methods available.
- The default request used, <classname>Zend_Controller_Request_Http</classname>,
- for instance, has methods for retrieving the request <acronym>URI</acronym>, path
- information, <varname>$_GET</varname> and <varname>$_POST</varname> parameters,
- etc.
- </para>
- <para>
- The request object is passed to the front controller, or if none is
- provided, it is instantiated at the beginning of the dispatch
- process, before routing occurs. It is passed through to every object
- in the dispatch chain.
- </para>
- <para>
- Additionally, the request object is particularly useful in testing.
- The developer may craft the request environment, including module,
- controller, action, parameters, <acronym>URI</acronym>, etc, and pass the request
- object to the front controller to test application flow. When paired
- with the <link linkend="zend.controller.response">response
- object</link>, elaborate and precise unit testing of <acronym>MVC</acronym>
- applications becomes possible.
- </para>
- </sect2>
- <sect2 id="zend.controller.request.http">
- <title>HTTP Requests</title>
- <sect3 id="zend.controller.request.http.dataacess">
- <title>Accessing Request Data</title>
- <para>
- <classname>Zend_Controller_Request_Http</classname> encapsulates access to
- relevant values such as the key name and value for the
- controller and action router variables, and all additional
- parameters parsed from the <acronym>URI</acronym>. It additionally allows access to
- values contained in the superglobals as public members, and
- manages the current Base <acronym>URL</acronym> and Request <acronym>URI</acronym>.
- Superglobal values cannot be set on a request object, instead use the
- <methodname>setParam()</methodname> and <methodname>getParam()</methodname> methods
- to set or retrieve user parameters.
- </para>
- <note>
- <title>Superglobal Data</title>
- <para>
- When accessing superglobal data through
- <classname>Zend_Controller_Request_Http</classname> as public member
- properties, it is necessary to keep in mind that the
- property name (superglobal array key) is matched to a
- superglobal in a specific order of precedence: 1. <constant>GET</constant>, 2.
- <constant>POST</constant>, 3. <constant>COOKIE</constant>, 4.
- <constant>SERVER</constant>, 5. <constant>ENV</constant>.
- </para>
- </note>
- <para>
- Specific superglobals can be accessed using a public method as
- an alternative. For example, the raw value of
- <varname>$_POST['user']</varname> can be accessed by calling
- <methodname>getPost('user')</methodname> on the request object. These
- include <methodname>getQuery()</methodname> for retrieving
- <varname>$_GET</varname> elements, and <methodname>getHeader()</methodname> for
- retrieving request headers.
- </para>
- <note>
- <title>GET and POST Data</title>
- <para>
- Be cautious when accessing data from the request object as
- it is not filtered in any way. The router and dispatcher
- validate and filter data for use with their tasks, but leave
- the data untouched in the request object.
- </para>
- </note>
- <note>
- <title>Retrieving the Raw POST Data</title>
- <para>
- As of 1.5.0, you can also retrieve the raw post data via the
- <methodname>getRawBody()</methodname> method. This method returns
- <constant>FALSE</constant> if no data was submitted in that fashion, but the
- full body of the post otherwise.
- </para>
- <para>
- This is primarily useful for accepting content when
- developing a RESTful <acronym>MVC</acronym> application.
- </para>
- </note>
- <para>
- You may also set user parameters in the request object using
- <methodname>setParam()</methodname> and retrieve these later using
- <methodname>getParam()</methodname>. The router makes use of this
- functionality to set parameters matched in the request <acronym>URI</acronym> into
- the request object.
- </para>
- <note>
- <title>getParam() Retrieves More than User Parameters</title>
- <para>
- In order to do some of its work, <methodname>getParam()</methodname> actually
- retrieves from several sources. In order of priority, these
- include: user parameters set via <methodname>setParam()</methodname>,
- <constant>GET</constant> parameters, and finally <constant>POST</constant>
- parameters. Be aware of this when pulling data via this
- method.
- </para>
- <para>
- If you wish to pull only from parameters you set via
- <methodname>setParam()</methodname>, use the
- <methodname>getUserParam()</methodname>.
- </para>
- <para>
- Additionally, as of 1.5.0, you can lock down which parameter
- sources will be searched. <methodname>setParamSources()</methodname>
- allows you to specify an empty array or an array with one or
- more of the values '_GET' or '_POST' indicating which
- parameter sources are allowed (by default, both are
- allowed); if you wish to restrict access to only '_GET'
- specify <methodname>setParamSources(array('_GET'))</methodname>.
- </para>
- </note>
- <note>
- <title>Apache Quirks</title>
- <para>
- If you are using Apache's 404 handler to pass incoming
- requests to the front controller, or using a PT flag with
- rewrite rules, <varname>$_SERVER['REDIRECT_URL']</varname>
- contains the <acronym>URI</acronym> you need, not
- <varname>$_SERVER['REQUEST_URI']</varname>. If you are using such
- a setup and getting invalid routing, you should use the
- <classname>Zend_Controller_Request_Apache404</classname> class instead
- of the default <acronym>HTTP</acronym> class for your request object:
- </para>
- <programlisting language="php"><![CDATA[
- $request = new Zend_Controller_Request_Apache404();
- $front->setRequest($request);
- ]]></programlisting>
- <para>
- This class extends the
- <classname>Zend_Controller_Request_Http</classname> class and simply
- modifies the autodiscovery of the request <acronym>URI</acronym>. It can be
- used as a drop-in replacement.
- </para>
- </note>
- </sect3>
- <sect3 id="zend.controller.request.http.baseurl">
- <title>Base Url and Subdirectories</title>
- <para>
- <classname>Zend_Controller_Request_Http</classname> allows
- <classname>Zend_Controller_Router_Rewrite</classname> to be used in subdirectories.
- <classname>Zend_Controller_Request_Http</classname> will attempt to automatically
- detect your base <acronym>URL</acronym> and set it accordingly.
- </para>
- <para>
- For example, if you keep your <filename>index.php</filename> in a
- webserver subdirectory named
- <filename>/projects/myapp/index.php</filename>, base <acronym>URL</acronym> (rewrite
- base) should be set to <filename>/projects/myapp</filename>. This string will
- then be stripped from the beginning of the path before
- calculating any route matches. This frees one from the necessity
- of prepending it to any of your routes. A route of
- <command>'user/:username'</command> will match <acronym>URI</acronym>s like
- <filename>http://localhost/projects/myapp/user/martel</filename> and
- <filename>http://example.com/user/martel</filename>.
- </para>
- <note>
- <title>URL Detection is Case Sensitive</title>
- <para>
- Automatic base <acronym>URL</acronym> detection is case sensitive, so make sure
- your <acronym>URL</acronym> will match a subdirectory name in a filesystem (even
- on Windows machines). If it doesn't, an exception will be raised.
- </para>
- </note>
- <para>
- Should base <acronym>URL</acronym> be detected incorrectly you can override it
- with your own base path with the help of the
- <methodname>setBaseUrl()</methodname> method of either the
- <classname>Zend_Controller_Request_Http</classname> class, or the
- <classname>Zend_Controller_Front</classname> class. The easiest
- method is to set it in <classname>Zend_Controller_Front</classname>,
- which will proxy it into the request object. Example usage to
- set a custom base <acronym>URL</acronym>:
- </para>
- <programlisting language="php"><![CDATA[
- /**
- * Dispatch Request with custom base URL with Zend_Controller_Front.
- */
- $router = new Zend_Controller_Router_Rewrite();
- $controller = Zend_Controller_Front::getInstance();
- $controller->setControllerDirectory('./application/controllers')
- ->setRouter($router)
- ->setBaseUrl('/projects/myapp'); // set the base url!
- $response = $controller->dispatch();
- ]]></programlisting>
- <note>
- <title>Fully-Qualified URL is not supported</title>
- <para>
- Passing a fully-qualified URL (ie: http://example.com/) to the
- <methodname>setBaseUrl</methodname> method is not supported, and
- will cause issues for both the usage describe above and when using
- the URL view helper. See ticket
- <ulink url="http://framework.zend.com/issues/browse/ZF-10923">
- ZF-10923
- </ulink> for more details.
- </para>
- </note>
- </sect3>
- <sect3 id="zend.controller.request.http.method">
- <title>Determining the Request Method</title>
- <para>
- <methodname>getMethod()</methodname> allows you to determine the
- <acronym>HTTP</acronym> request method used to request the current resource.
- Additionally, a variety of methods exist that allow you to get
- boolean responses when asking if a specific type of request has
- been made:
- </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>
- The primary use case for these is for creating RESTful <acronym>MVC</acronym>
- architectures.
- </para>
- </sect3>
- <sect3 id="zend.controller.request.http.ajax">
- <title>Detecting AJAX Requests</title>
- <para>
- <classname>Zend_Controller_Request_Http</classname> has a rudimentary
- method for detecting <acronym>AJAX</acronym> requests:
- <methodname>isXmlHttpRequest()</methodname>. This method looks for an
- <acronym>HTTP</acronym> request header <emphasis>X-Requested-With</emphasis> with
- the value 'XMLHttpRequest'; if found, it returns <constant>TRUE</constant>.
- </para>
- <para>
- Currently, this header is known to be passed by default with the
- following JS libraries:
- </para>
- <itemizedlist>
- <listitem>
- <para>Prototype and Scriptaculous (and libraries derived from Prototype)</para>
- </listitem>
- <listitem><para>Yahoo! UI Library</para></listitem>
- <listitem><para>jQuery</para></listitem>
- <listitem><para>MochiKit</para></listitem>
- </itemizedlist>
- <para>
- Most <acronym>AJAX</acronym> libraries allow you to send custom
- <acronym>HTTP</acronym> request headers; if your library does not send this header,
- simply add it as a request header to ensure the
- <methodname>isXmlHttpRequest()</methodname> method works for you.
- </para>
- </sect3>
- </sect2>
- <sect2 id="zend.controller.request.subclassing">
- <title>Subclassing the Request Object</title>
- <para>
- The base request class used for all request objects is the abstract
- class <classname>Zend_Controller_Request_Abstract</classname>. At its most
- basic, it defines the following methods:
- </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>
- The request object is a container for the request environment. The
- controller chain really only needs to know how to set and retrieve the
- controller, action, optional parameters, and dispatched status. By
- default, the request will search its own parameters using the
- controller or action keys in order to determine the controller and
- action.
- </para>
- <para>
- Extend this class, or one of its derivatives, when you need the
- request class to interact with a specific environment in order to
- retrieve data for use in the above tasks. Examples include <link
- linkend="zend.controller.request.http">the <acronym>HTTP</acronym>
- environment</link>, a <acronym>CLI</acronym> environment, or a
- <acronym>PHP</acronym>-GTK environment.
- </para>
- </sect2>
- </sect1>
- <!--
- vim:se ts=4 sw=4 et:
- -->
|