简体   繁体   中英

ZF2: Where does the controller return/result get manipulated by the MVC?

I am working on a RESTful API in Zend Framework 2. I use the AbstractRestfulController to handle requests. In that controller I want to directly return an array or object (of a custom model class), not a JsonModel . That stuff and the conversion of the result to arrays (as a preparation for the JSON encoding) should happen later automatically.

  • I tried to catch the MvcEvent::EVENT_DISPATCH event to manipulate the $e->getResult() value but when I return an associative array in the controller I get a ViewModel in the result instead of the plain data passed in by the controller method.

  • I tried to create a custom view strategy by implementing the ListenerAggregateInterface class. In the ViewEvent::EVENT_RESPONSE event catch, I dumped the $e->getResult() value and got the already encoded result. Also here, I need the plain result to prepare it for encoding.

Where can I hook in to manipulate the controller's plain return value before encoding to JSON? Where does ZF2 generally manipulate the returned value in the MVC lifecycle?

Thank you in advance!

I don't have so much time to investigate in this issue, but my guess is that you may omit to stop event propagation when you attached a listener to MvcEvent::EVENT_DISPATCH. So what you set as the event result is probably overridden later in the dispatch process.

Try to attach your callback with a higher priority and stop the propagation ($e->stopPropagation() from the callback), since the event manager won't stop the propagation by itself until one or the other callback returns a Zend\\StdLib\\ResponseInterface object.

Anyway, I know you probably have good reasons trying to "hack" the dispatch process this way, but I tend to think that there could be even better reasons to adapt your code to fit the default process ;)

Here , zf2 creates a ViewModel in case an assoc array is detected in the result, registered at priority -80. According to this documentation page this is the first event catch changing the result returned by the controller.

What I did wrong is attaching my MvcEvent::EVENT_DISPATCH to the $application->getEventManager() instead of $application->getEventManager()->getSharedManager() ( like zf2 does ). I don't understand yet what the difference is, but it works.

Here is how I registered the event in the onBootstrap method:

$application->getEventManager()->getSharedManager()->attach(
    __NAMESPACE__,
    MvcEvent::EVENT_DISPATCH,
    array($this, 'createJsonModelFromResult'),
    -10
    // priority of -10 because at priority 1 the mvc
    //  runs the actual controller method
);

At the end of the createJsonModelFromResult method I also added $e->stopPropagation(); because we already found the matching ViewModel .

Now the $e->getResult() value is exactly the same as returned in my controller actions and I can prepare it for JSON encoding. Cool!

I have no idea how you want to return an array or Object. Usually people make a DTO (Data Transfer Object), serialize it, and then send it. In this method the DTO at the end converts to JSON.

What format do you want to use in response? String (serialized DTO), XML, or something else? You can create a class extending ViewModel and serialize your array for your format.

Anyway, you do not need to get MVC_EVENT.

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM