1

I'm implementing a REST service with Zend Framework 2. The routing and controller works very well, but now I need to display an update form in the view.

In Zend Framework 1 I could simply do a POST with the "magic" GET parameter ?_method=PUT, which would make ZF think it was actually a PUT request. Meaning the form tag looked something like:

<form action="/resource/1/?_method=PUT" method="POST"> 

The above doesn't work in ZF2: Instead of running the update() method in my controller the create() method is exectued.

How do I simulate a PUT request in ZF2? Can I do it without using JavaScript?

2 Answers 2

2

I think ZF2 doesn't handle the situation like yours at all. You have to handle it by yourself. See the code below:

class Module implements BootstrapListenerInterface { public onBootstrap(EventInterface $event) { $event->getApplication() ->getEventManager() ->attach(MvcEvent::EVENT_ROUTE, function(MvcEvent $e){ $request = $e->getRequest(); $m = $request->getQuery('_method'); switch ($m) { case Request::METHOD_PUT: $request->setMethod(Request::METHOD_PUT); break; case Request::METHOD_DELETE: $request->setMethod(Request::METHOD_DELETE); break; case Request::METHOD_POST: $request->setMethod(Request::METHOD_POST); break; case Request::METHOD_GET: $request->setMethod(Request::METHOD_GET); break; default: break; } }); } } 
Sign up to request clarification or add additional context in comments.

1 Comment

This is a better solution than mine, since it will actually do what I asked in the question ("simulate a PUT request"). Marking as correct answer!
1

Once again I'm answering my own question.

The "magic" is gone from ZF2, we need to fix things ourselves. This is how I did it:

class ResourceController extends AbstractRestfulController { public function __construct() { $this->addHttpMethodHandler('POST', array($this, 'handlePostPut')); } public function handlePostPut($event) { $request = $event->getRequest(); if ('put' == strtolower($request->getQuery('_method'))) { $routeMatch = $event->getRouteMatch(); $id = $this->getIdentifier($routeMatch, $request); $data = $this->processBodyContent($request); if ($id !== false) { return $this->update($id, $data); } return $this->replaceList($data); } else { return $this->processPostData($request); } } } 

The key is the addHttpMethodHandler() method in the AbstractRestfulController class. With this we can override which controller function is being run for a specific HTTP method. In this case I'm overriding the POST method to call my handlePostPut() function instead. In that function I'm checking whether my "magic" query parameter is present, and if so I'm just doing what the controller would have done if it was a put request. Otherwise I'm treating it as a normal POST request.

There is one caveat though: The action parameter in the RouteMatch object will be set to post even if we're treating it as a put. I don't know of a good way to fix that at the moment.

1 Comment

It's a nice solution. I've just offered mine in more generic way.

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.