Adding PUT variables to Request Object in Zend Framework

When I wrote recently about testing web services within Zend Framework, I missed out a really key piece of information! I didn't explain how I was reading the PUT vars in my controller code in the first place - so I'll rectify that omission now.

Its very simple: I have extended Zend_Controller_Action with my own, and all controllers inherit from here. This has a routeAction() which grabs the incoming variables from a PUT request and sets them as parameters within the usual $this->getRequest() scope, then forwards on the request. Here is my class:

class My_Controller_Action extends Zend_Controller_Action
{
    public function routeAction()    
    {
        // handle grabbing PUT vars
        if($this->getRequest()->isPut()) {
            parse_str($this->getRequest()->getRawBody(), $params);
            foreach($params as $key => $value) {
                $this->getRequest()->setParam($key, $value);
            }
        }
        $this->_forward(strtolower($this->getRequest()->getMethod()));
    }
}

So in my controller code, I simply call out to $this->getRequest()->getParam('name') or whatever, and in my tests I can set those parameters as I showed in my other article.

I hope this makes sense, its one of those things I set up once and use a lot (and now I'll be able to refer to how I did it!), if you have any queries, comments, improvements or if this helps you then please leave a comment - I haven't come across anyone else doing anything similar but I know there must be, so let me know!

7 thoughts on “Adding PUT variables to Request Object in Zend Framework

  1. in your code you have:
    [geshi lang=php]
    foreach($params as $key => $value) { $this->getRequest()->setParam($key, $value);
    }
    [/lang]

    wouldn't that be better to have the object returned by the getRequest cached so that you don't spend time calling it in each loop?
    eg
    [geshi lang=php]
    $myReq = $this->getRequest();
    foreach($params as $key => $value) {
    $myReq->setParam($key, $value);
    }
    [/lang]

  2. BinaryKitten: You certainly could do - I know my system deals only with about five incoming parameters so the change would be tiny. In principle though you are quite correct and repeatedly fetching something in a loop is a Bad Thing (TM)

  3. Lorna,

    you should consider putting the parse_str() logic into the request object, rather than a controller. You are dealing with details of how request works (namely, the raw request data), thus you are coupling your controller to the request more tightly than you'd have to. Plus, by putting that logic into the request, it's easier to reuse.

    Stefan

    • Or one can have some kind of RequestHandler class which responsibility is to populate the Request object. This happens differently for example if you application is called from command line.

      A step further: the action controller can defines its parameters via the parameter list and the front controller can populate them via Reflection API. This way you controller seems like a real function.

      @Lorna: to consider what to put to a controller is a good technique is to think about what would be if your controller should work in CLI.

  4. I like the sound of these - can either of you refer me to an example of how I would actually do this? I'm a bit of a ZF newbie so although I can usually get things working, I'm sure there are better ways like these you suggest

Leave a Reply

Please use [code] and [/code] around any source code you wish to share.

You may use these HTML tags and attributes: <a href="" title=""> <abbr title=""> <acronym title=""> <b> <blockquote cite=""> <cite> <code> <del datetime=""> <em> <i> <q cite=""> <strike> <strong>