Skip to end of metadata
Go to start of metadata

<ac:macro ac:name="unmigrated-inline-wiki-markup"><ac:plain-text-body><![CDATA[

<ac:macro ac:name="unmigrated-inline-wiki-markup"><ac:plain-text-body><![CDATA[

Zend Framework: Zend_http_Request Component Proposal

Proposed Component Name Zend_http_Request
Developer Notes http://framework.zend.com/wiki/display/ZFDEV/Zend_http_Request
Proposers Sylvain to contact me
Revision 1.1 - 1 August 2006: Updated from community comments. (wiki revision: 27)

Table of Contents

1. Overview

Allow to personalize routing strategy in a request container

2. References

3. Component Requirements, Constraints, and Acceptance Criteria

  • Correctly reads a developers mind for intent
  • Generates strict PHP 5.x object oriented code codifying the read intent
  • Performs with less than a 0.2 second lag from though to start of execution

4. Dependencies on Other Framework Components

  • Zend_Controller_Dispatcher_Token

5. Theory of Operation

The component should be instantiated once in index.php and should be accessible from everywhere in ZF

6. Milestones / Tasks

zone: Missing {zone-data:milestones}

7. Class Index

  • Zend_Controller_Dispatcher_Token
  • Zend_http_Request

8. Use Cases

flexible capabilities to route

9. Class Skeletons

Here is an class with code filled in. It is based on my 7 points below, a Martel's code and comments. I think this code shows more clearly how this class is proposed to work.

]]></ac:plain-text-body></ac:macro>

]]></ac:plain-text-body></ac:macro>

Labels:
None
Enter labels to add to this page:
Please wait 
Looking for a label? Just start typing.
  1. Jun 23, 2006

    <p>This is the third (or more) Router class.</p>

    <p>I think there really needs to be in a Zend_Http_Request class. It would clear up some of the issues here and make it easy to make the Router optional as well. </p>

    <p>A standard container for the request that would also figure out things like the base path for creating URLs and <base href=""> which often required when using clean URLs – needed by Routers, the Dispatcher, and for the response as well. </p>

    <p>There are so many things that fan out design-wise from the request that has been troubling that there has not been a container. My concern is that – while insular thinking is fine for components – I don't see the expansive discussion of many potential ways to organize the base classes and controllers. </p>

    <p>Where to put the Request class and what services it provides – whether new or that other classes are currently doing – is a prime example of this kind of balancing organization. </p>

    1. Jun 23, 2006

      <p>hi, <br />
      I don't understand what you mean by Zend_Http_Request? is it a http client, an other way to put the request class I suggested in order to make a request container?<br />
      I don't understand also why router and dispatcher need <span style="text-decoration: line-through;">clean URLs</span> and <base href="">. I saw the dispatcher only need a token built by the router which need <span style="text-decoration: line-through;">clean decomposed URI</span> provide by the request class parameterized by user.</p>

      1. Jun 24, 2006

        <p>No, not a client (there alreay is one). I mean a Request container. My point is that once there is a request container that provides some of the basic services (such as base URL, etc.) that the other code, like the Dispatcher and routers, becomes simpler. It may even be possible to remove any dependencies on a Router from other controller classes if routers simply modified the Request containter before giving it to a controller to dispatch. Simpler code that achieves the same goals would be a good thing. </p>

        <p>Perhaps they are somewhere, but I have not seen what the list of requirements are the request->route->dispatch phase of the Front Controller are for the ZF. </p>

        1. Jun 26, 2006

          <p>OK, I've understood what you mean. So I propose now a request container squeletton with useful services to personalise and which are accessible everywhere. I'm volontary not implemented it to have a better view on this componant. Thx for your remarks.</p>

  2. Aug 15, 2006

    <p>With Gavin's post to the mail list, I would like to restart the discussion of this class proposal. I have been pestering Sylvain from the start and I hope further changes don't drive him crazy. <ac:emoticon ac:name="wink" /></p>

    <p>I think my main comment are that this class should be as simple as possible. But this class is also a data provider to the Front Controller, Routers and Action Controller, so it needs to support their work. How much goes here and how much stays in those classes is and important design question. For example, the Request may do the job that the Dispatcher_Token class is currently doing in convey information about the contorller/action to dispatch. Sylvain has added some of that functionality above. Conversely the Request could just be a container for GET/POST values.</p>

    <p>Another question is whether the Base URL is carried by the Request. It is not exactly a core "request" function, but as I can see the Request being passed into the Action Controllers (unlike the Router) that information is handy to have for things like URL generation. Sylvain currently has that information here in the Request. </p>

    <p>For the main design of the Request class, I think I would diverge from Sylvain's interface and implement something that will feel similar to the GET/POST/REQUEST superglobals that PHP programmers are used to. So I propose the following:</p>

    <p>1. Provide a method to determine the request method, either isPost() (return true/false) or getMethod() (returns 'GET' or 'POST'). </p>

    <p>2. Provide a basic interface to request vars via __get()/get() that either give access to either $_GET or $_POST depending on the request method, or access to something like $_REQUEST but perhaps dealing with GPC overwriting problems. </p>

    <p>3. Provide an method to access the $_GET array.</p>

    <p>4. Provide an method to access the $_POST array.</p>

    <p>5. Provide an method to access the Base URL.</p>

    <p>6. Provide an method to access the PATH_INFO. This method should use whatever server variables are available depending on platform to provide a consistent PATH_INFO value. </p>

    <p>7. Provide the features of the Dispatcher Token with methods to access the controller name, action name and arg array. That is handy elsewhere too and there have been request to have this available in Actions. </p>

    <p>I would also note that this class provides the base functionality for Filter_Input class. </p>

    1. Aug 16, 2006

      <p>I agree that this class should be as simple as possible too. </p>

      <p>I think the base URL should be carried by the request, along with other page-related "server" things like whether https is on or off and if the request is a POST or GET.</p>

      <p>Your points 1 - 6 make sense to me too. </p>

      <p>Not sure why you need 7 though sa they are already available in the action. Wouldn't harm to put them their though, I'd rather it was there as a Distach_token. e.g.</p>
      <ac:macro ac:name="code"><ac:plain-text-body><![CDATA[
      $controllerName = $request->getToken()->getControllerName();
      ]]></ac:plain-text-body></ac:macro>

      1. Aug 17, 2006

        <p>I have posted it internally for the time being, but as well I can hint what it may be used like in the future. The idea is to discard the token altogether and use a request object in it's place. Which will make a router optional by the way.</p>

        <ac:macro ac:name="code"><ac:plain-text-body><![CDATA[
        class Zend_Controller_RewriteRouter implements Zend_Controller_Router_Interface
        {

        public function __construct();
        public function addRoute($name, Zend_Controller_Router_Route_Interface $route);
        public function addRoutes($routes);
        public function addConfig(Zend_Config $config, $section);

        public function getRoute($name);
        public function getCurrentRoute();
        public function getRoutes();

        public function route(Zend_Controller_Request $request)
        {
        foreach (array_reverse($this->_routes) as $route) {
        if ($params = $route->match($request->getPathInfo())) {
        foreach ($params as $key => $val)

        Unknown macro: { $request->set($key, $value); }

        }
        }
        return $request;
        }
        }
        ]]></ac:plain-text-body></ac:macro>

        <p>And a dispatcher:</p>

        <ac:macro ac:name="code"><ac:plain-text-body><![CDATA[
        class Zend_Controller_Dispatcher implements Zend_Controller_Dispatcher_Interface
        {

        // user may specify own values for these
        public $controller = 'index';
        public $action = 'index';
        public $controllerVar = 'controller';
        public $actionVar = 'index';

        public function __construct();

        public function setControllerVar($name);
        public function setActionVar($name);
        public function setDefaultController($name);
        public function setDefaultAction($name);

        protected function _formatName($unformatted);
        public function formatActionName($unformatted);
        public function formatControllerName($unformatted);

        public function setControllerDirectory($dir);
        public function isDispatchable(Zend_Http_Request $request);

        public function dispatch(Zend_Http_Request $request) {

        if (!$dispatcher->isDispatchable($request))

        Unknown macro: { throw new Zend_Controller_Router_Exception('...'); }

        $controllerName = $request->get($this->controllerVar);
        $className = $this->formatControllerName($controllerName);

        Zend::loadClass($className, $this->_directory);

        (...)

        // this code needs some refactoring as isDispatchable and dispatch
        // shouldn't share the same code

        }
        ]]></ac:plain-text-body></ac:macro>

  3. Aug 17, 2006

    <p>Personaly, I thought my interface as martel says : as a request object. And this object can be accessible everywhere in the application. (Christopher remarks bring me in this way)<br />
    This object should provide all we need in your routing strategy and should be flexible as possible.<br />
    So about christopher proposal, I whould like to do some remarks now <ac:emoticon ac:name="wink" />. I think this proposal focalize too much on GET or POST methods on request process. Provide a method to access the $_GET or $_POST array is not enought general. Provide a method to access a REQUEST is better because a request could be GET , POST  , url rewriting or even CLI. In this fact, the request object is an abstraction of all methods access (an encapsulation of these methods). A method to access the PATH_INFO is, according to me, too specific to an interface. A method to access <strong>currentRoute</strong> (like in rewriterouter) or to access <strong>currentrequest</strong> l(ike in my proposal) is more general and abstract.</p>

    <p>I'm ok about the point 7. Rob says it's already implemented in Actioncontroller but I think it's better to provide this by a request object which can be accessible everywhere.</p>

  4. Aug 21, 2006

    <p>I have posted updated code based to further show the idea of providing a Request container that also provides some of the PATH_INFO and Base URL functionality currently in the Router and encapsulates the controller params like the Token currently does. </p>

    <p>It is the second code block in the Class Skeletons sections above.</p>

    1. Aug 22, 2006

      <p>Since __get() and __set() are being used and accessing array elements, why not also implement Iterator and Countable (maybe RecursiveIterator, for the possiblity of nested array elements in the POST and/or GET arrays).</p>

      <p>What exactly is the params() array for? Would it be used when passing the object instance between other objects and methods?</p>

    2. Aug 23, 2006

      <p>Could we put parsing of /path/info/url/params into the request object? This would then allow it to encapsulate get, post, and path info easily.</p>

      1. Aug 27, 2006

        <p>That should be in there. That is the intention of the getPathInfo() and setPathInfo() methods. </p>

  5. Aug 28, 2006

    <p>I'd like to make sure I understand the overall intent of how this class is to be used. Let's assume you need to be able to edit a person so you have a request like:<br />
    whatever.com/person/edit/id/27</p>

    <p>The editAction of your Person Controller get's fired off.<br />
    Currently we would use:<br />
    $personId = $this->_getParam('id');<br />
    To get the person to edit. </p>

    <p>Under the new approach, is the intent to use something like:<br />
    $personId = $this->request->id;</p>

    <p>Just want to make sure I understand.</p>

    1. Aug 29, 2006

      <p>The specifics have not been defined. I think that $personId = $this->_getParam('id'); would work for backward compatabilty. And yes, somthing like $personId = $this->request->id; might be the new approach. </p>

  6. Aug 28, 2006

    <p>Is it necessary to have methods for both GET and POST accessors? Wouldn't a request be either one or the other? getGET() and setGET() seems a little awkward.</p>

    <p>The other query I had was to do with populating the request variables. If we use a 'standard' router (i.e. using the query string for variable pairs) then they are written to the 'get' array. But how do variables from a rewriteRouter get passed and do they also belong in the 'get' array or just in 'request'?</p>

    1. Aug 29, 2006

      <p>I agree that getGET() and setGET() are awkward. They are there to provide compelete, direct access to those arrays. You really only need to use get()/set() and the class gives you the right data depending on the request method. The only other one actually needed is getGET() because there can be GET parameters along with a POST. </p>

      <p>As far as the Router, the idea is that the Router would become a filter that is passed a Request object and would set the controller, action and params values in the Request (instead of using a Dispatcher_Token).</p>

      1. Aug 29, 2006

        <p>You don't think we could get slightly tricky and allow this to extend ArrayAccess?</p>

        <p>so:-</p>

        <p>$request->id = getting the current request variable $id from GET,POST or the dispatchToken</p>

        <p>$request<ac:link><ri:page ri:content-title="'POST'" /></ac:link>->id = Post variables (get/set)<br />
        $request<ac:link><ri:page ri:content-title="'GET'" /></ac:link>->id = Get variables (get/set)<br />
        $request<ac:link><ri:page ri:content-title="'PARAM'" /></ac:link>->id = dispatchToken variables (get/set)</p>

        <p>You lose some potentially crufty methods and gain the opportunity to extend the different containers that can feed data to the request object (maybe even $request<ac:link><ri:page ri:content-title="'ARGS'" /></ac:link> for console?)</p>

  7. Aug 29, 2006

    <p>Damn Wiki!</p>

    <p>That should have read:-</p>
    <ac:macro ac:name="code"><ac:plain-text-body><![CDATA[
    $request['POST']->id
    $request['GET']->id

    ...etc...
    ]]></ac:plain-text-body></ac:macro>

  8. Oct 10, 2006

    <ac:macro ac:name="note"><ac:parameter ac:name="title">Zend Comment</ac:parameter><ac:rich-text-body>
    <p>This proposal is superseded by <a class="external-link" href="http://framework.zend.com/wiki/display/ZFPROP/Zend_Http_Request">http://framework.zend.com/wiki/display/ZFPROP/Zend_Http_Request</a> and incorporated in <a class="external-link" href="http://framework.zend.com/wiki/display/ZFPROP/MVC+Reorganization+Proposal">http://framework.zend.com/wiki/display/ZFPROP/MVC+Reorganization+Proposal</a>.</p></ac:rich-text-body></ac:macro>