Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Trigger new event to allow updating the response based on view data at one central place #2386

Open
wants to merge 1 commit into
base: 3.x
Choose a base branch
from
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Jump to
Jump to file
Failed to load files.
Diff view
Diff view
1 change: 1 addition & 0 deletions DependencyInjection/FOSRestExtension.php
Original file line number Diff line number Diff line change
Expand Up @@ -293,6 +293,7 @@ private function loadView(array $config, XmlFileLoader $loader, ContainerBuilder
$config['view']['empty_content'],
$config['view']['serialize_null'],
]);
$defaultViewHandler->addMethodCall('setEventDispatcher', [new Reference('event_dispatcher')]);
}

private function loadException(array $config, XmlFileLoader $loader, ContainerBuilder $container): void
Expand Down
27 changes: 27 additions & 0 deletions Resources/doc/2-the-view-layer.rst
Original file line number Diff line number Diff line change
Expand Up @@ -198,6 +198,33 @@ data transformer. Fortunately, the FOSRestBundle comes with an
This way, the data structure remains untouched and the person can be assigned to
the task without any client modifications.

Update the Response based on View Data
--------------------------------------

If you have the need to globally modify the response depending on the view data
you can use the ``ViewResponseEvent``. It allows you to do some custom stuff
at one central place and reduce repetitive work.

Here's an example how to use it:

.. code-block:: php
namespace App\EventListener;

use FOS\RestBundle\View\ViewResponseEvent;
use Symfony\Component\EventDispatcher\Attribute\AsEventListener;

#[AsEventListener]
class PaginationViewResponseListener
{
public function __invoke(ViewResponseEvent $event): void
{
$view = $event->getView(); // you have access to the view and the response
$response = $event->getResponse();
// ...
}
}


Configuration
-------------

Expand Down
12 changes: 12 additions & 0 deletions View/ViewHandler.php
Original file line number Diff line number Diff line change
Expand Up @@ -19,6 +19,7 @@
use Symfony\Component\HttpFoundation\Response;
use Symfony\Component\HttpKernel\Exception\UnsupportedMediaTypeHttpException;
use Symfony\Component\Routing\Generator\UrlGeneratorInterface;
use Symfony\Contracts\EventDispatcher\EventDispatcherInterface;

/**
* View may be used in controllers to build up a response in a format agnostic way
Expand Down Expand Up @@ -52,6 +53,7 @@ final class ViewHandler implements ConfigurableViewHandlerInterface
private $urlGenerator;
private $serializer;
private $requestStack;
private $dispatcher = null;
private $options;

private function __construct(
Expand Down Expand Up @@ -198,9 +200,19 @@ public function createResponse(View $view, Request $request, string $format): Re
$response->headers->set('Content-Type', $mimeType);
}

if (null !== $this->dispatcher) {
$event = new ViewResponseEvent($view, $response, $request);
$this->dispatcher->dispatch($event);
}

return $response;
}

public function setEventDispatcher(EventDispatcherInterface $dispatcher): void
{
$this->dispatcher = $dispatcher;
}

/**
* Gets a response HTTP status code from a View instance.
*
Expand Down
47 changes: 47 additions & 0 deletions View/ViewResponseEvent.php
Original file line number Diff line number Diff line change
@@ -0,0 +1,47 @@
<?php

/*
* This file is part of the FOSRestBundle package.
*
* (c) FriendsOfSymfony <http://friendsofsymfony.github.com/>
*
* For the full copyright and license information, please view the LICENSE
* file that was distributed with this source code.
*/

namespace FOS\RestBundle\View;

use Symfony\Component\HttpFoundation\Request;
use Symfony\Component\HttpFoundation\Response;

/**
* Allows to update the Response an the basis of view data.
*/
class ViewResponseEvent
{
private $view;
private $response;
private $request;

public function __construct(View $view, Response $response, Request $request)
{
$this->view = $view;
$this->response = $response;
$this->request = $request;
}

public function getView(): View
{
return $this->view;
}

public function getResponse(): Response
{
return $this->response;
}

public function getRequest(): Request
{
return $this->request;
}
}