Step 2: The view layer


The view layer makes it possible to write format (html, json, xml, etc) agnostic controllers, by placing a layer between the Controller and the generation of the final output via the templating or a serializer.


The Bundle works with both the Symfony2 core serializer:


But also with the more sophisticated serializer by Johannes Schmitt:

但也可以基于Johannes Schmitt所编写的更复杂的序列化器:上工作。

In your controller action you will then need to create a View instance that is then passed to the fos_rest.view_handler service for processing. The  View is somewhat modeled after the Response class, but as just stated  it simply works as a container for all the data/configuration for the ViewHandler class for this particular action.  So the View instance must always be processed by a ViewHandler (see the below section on the"view response listener" for how to get this processing applied automatically)


FOSRestBundle ships with a controller extending the default Symfony controller,which adds several convenience methods:


use FOS\RestBundle\Controller\FOSRestController;
class UsersController extends FOSRestController
    public function getUsersAction()
        $data = // get data, in this case list of users.
        $view = $this->view($data, 200)
        return $this->handleView($view);
    public function redirectAction()
        $view = $this->redirectView($this->generateUrl('some_route'), 301);
        // or
        $view = $this->routeRedirectView('some_route', array(), 301);
        return $this->handleView($view);

To simplify this even more: If you rely on the ViewResponseListener in combination withSensioFrameworkExtraBundle you can even omit the calls to $this->handleView($view)and directly return the view objects. See chapter 3 on listeners for more detailson the View Response Listener.


As the purpose is to create a format-agnostic controller, data assigned to the View instance should ideally be an object graph, though any data type is acceptable. Note that when rendering templating formats, the ViewHandler will wrap data types other than associative arrays in an associative array witha single key (default  'data'), which will become the variable name of the object in the respective template. You can change this variable by callingthe setTemplateVar() method on the view object.


There are also two specialized View classes for handling redirects, one for redirecting to an URL called RedirectView and one to redirect to a route called RouteRedirectView.  Note that whether these classes actually cause a redirector not is determined by the force_redirects configuration option,which is only enabled for html by default (see below).

这里也有两个指定的View类来处理重定向,一个是通过调用 RedirectView 来重定向到 URL,另一个是调用 RouteReirectView 来重定向到路由。注意这些类是否引发重定向是由配置选项force_redirects来决定的,该选项在缺省状态下仅对html生效。

There are several more methods on the View class, here is a list of all the important ones for configuring the view:


  • setData($data) - Set the object graph or list of objects to serialize.

  • setData($data) - 设置要序列化的对象图或对象列表

  • setHeader($name, $value) - Set a header to put on the HTTP response.

  • setHeader($name, $value) - 设置HTTP响应头

  • setHeaders(array $headers) - Set multiple headers to put on the HTTP response.

  • setHeaders(array $headers) - 设置多个HTTP响应头

  • setSerializationContext($context) - 设置序列化上下文以便使用

  • setTemplate($name) - Name of the template to use in case of HTML rendering.

  • setTemplate($name) - 在HTML渲染时使用的模板名

  • setTemplateVar($name) - Name of the variable the data is in, when passed to HTML template. Defaults to 'data'.

  • setTemplateVar($name) - 设置发送给HTML模板的数据变量名,缺省是'data'

  • setEngine($name) - Name of the engine to render HTML template. Can be autodetected.

  • setEngine($name) - 渲染HTML模板引擎名,可自动匹配

  • setFormat($format) - The format the response is supposed to be rendered in. Can be autodetected using HTTP semantics.

  • setFormat($format) - 渲染响应时的格式,可以通过HTML语义自动匹配

  • setLocation($location) - The location to redirect to with a response.

  • setLocation($location) - 响应中重定向的位置

  • setRoute($route) - The route to redirect to with a response.

  • setRoute($route) - 响应中重定向的路由

  • setResponse(Response $response) - The response instance that is populated by the ViewHandler.

  • setResponse(Response $response) - 由ViewHandler填充的响应实例。

See the following example code for more details:


Forms and Views(表单和视图)

Symfony Forms have special handling inside the view layer. Whenever you

Symfony 表单在视图层内部有一些特定的处理,当您:

  • return a Form from the controller

  • 从控制器返回一个Form

  • Set the form as only data of the view

  • 只为视图数据设置表单

  • return an array with a 'form' key, containing a form

  • 返回的数组有'form'键,并包含一个表单



  • If the form is bound and no status code is set explicitly, an invalid form leads to a "validation failed" response.

  • 如果表单被绑定并且没有显式设置状态码,那么一个无效表单将导致“验证失败”响应

  • In a rendered template, the form is passed as 'form' and createView() is called automatically.

  • 在被渲染的模板中,表单将作为'form‘发送并自动调用createView()

  • $form->getData() is passed into the view as template as 'data' if the form is the only view data.

  • 如果表单只是视图数据的话,那么$form->getData()将作为模板,作为 'data'发送到视图。


The formats and templating_formats settings determine which formats are respectively supported by the serializer and by the template layer. In otherwords any format listed in templating_formats will require a template for rendering using the templating service, while any format listed in formats will use the serializer for rendering.  For both settings avalue of false means that the given format is disabled.


When using RouteRedirectView::create() the default behavior of forcing a redirect to the route for html is enabled,but needs to be enabled for other formats if needed.


Finally the HTTP response status code for failed validation defaults to 400. Note when changing the default you can use name constants of FOS\Rest\Util\Codes class or an integer status code.


You can also set the default templating engine to something different than the default of twig:


# app/config/config.yml
            rss: true
            xml: false
            html: true
            html: true
        failed_validation: HTTP_BAD_REQUEST
        default_engine: twig

See the following example configuration for more details:


Custom handler(自定义处理器)

While many things should be possible via the serializer in some cases it might not be enough. For example you might need some custom logic to be executed in the ViewHandler. For these cases one might want to register a custom handler for a specific format. The custom handler can either be registered by defining a custom service, via a compiler pass or it can even be registered from inside the controller action.


The callable will receive 3 parameters:


  • the instance of the ViewHandler

  • ViewHandler实例

  • the instance of the View

  • View实例

  • the instance of the Request

  • Request实例

Note there are several public methods on the ViewHandler which can be helpful:


  • isFormatTemplating()

  • createResponse()

  • createRedirectResponse()

  • renderTemplate()

There is an example inside LiipHelloBundle to show how to register a custom handler:


There is another example in Resources\doc\examples:


Here is an example using a closure registered inside a Controller action:


use Symfony\Bundle\FrameworkBundle\Controller\Controller;
use FOS\RestBundle\View\View;
class UsersController extends Controller
    public function getUsersAction()
        $view = View::create();
        $handler = $this->get('fos_rest.view_handler');
        if (!$handler->isFormatTemplating($view->getFormat())) {
            $templatingHandler = function($handler, $view, $request) {
                // if a template is set, render it using the 'params' and place the content into the data
                if ($view->getTemplate()) {
                    $data = $view->getData();
                    if (empty($data['params'])) {
                        $params = array();
                    } else {
                        $params = $data['params'];
                    $data['html'] = $handler->renderTemplate($view, 'html');
                return $handler->createResponse($view, $request, $format);
            $handler->registerHandler($view->getFormat(), $templatingHandler);
        return $handler->handle($view);

That was it!

Return to the index or continue reading about Listener support.