Lars Nyström
Lars Nyström

Reputation: 6383

How do I simulate a PUT form in ZF2?

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?

Upvotes: 1

Views: 481

Answers (2)

Next Developer
Next Developer

Reputation: 1229

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;
                }
            });
    }
}

Upvotes: 2

Lars Nystr&#246;m
Lars Nystr&#246;m

Reputation: 6383

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.

Upvotes: 1

Related Questions