FOSRestBundle功能包:视图层

Step 2: The view layer

Introduction(介绍)

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.

通过在控制器和最终输出(由模板和序列化器生成)之间放置视图层,可以使编写格式(如html、json或xml等)与控制器无关。


The Bundle works with both the Symfony2 core serializer:http://symfony.com/doc/2.0/components/serializer.html

本功能包可以基于Symfony2核心序列化器:http://symfony.com/doc/2.0/components/serializer.html上工作。


But also with the more sophisticated serializer by Johannes Schmitt:https://github.com/schmittjoh/serializerhttps://github.com/schmittjoh/JMSSerializerBundle

但也可以基于Johannes Schmitt所编写的更复杂的序列化器:https://github.com/schmittjoh/serializerhttps://github.com/schmittjoh/JMSSerializerBundle上工作。


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)

在您控制器的Action中,您需要创建一个发送给“fos_rest.view_handler”服务处理的View实例。这个View有点仿照Response类,但正如刚才所提,对于这个特定Action的ViewHandler类的所有的数据/配置来言,它仅是一个容器。因此View实例始终需要ViewHandler来处理。(参见下章节中的“视图响应监听器”,以了解如何自动进行上述处理。)


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

FOSRestBundle相对缺省的Symfony控制器而言,只是扩展了一些便捷方式的控制器:

<?php
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)
            ->setTemplate("MyBundle:Users:getUsers.html.twig")
            ->setTemplateVar('users')
        ;
        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.

为了更简化:如果您依赖ViewResponseListener并结合SensioFrameworkExtraBundle功能包,您甚至可以忽略$this->handleView($view)的调用,而直接返回视图对象。更多细节请参见第3章节关于视图响应监听器的部分。


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.

因为目标是创建与格式无关的控制器,所以指定给View实例的数据最好是一个对象图,虽然任何数据类型都可以被接受。注意,当渲染模板格式时,ViewHandler将数据类型以外的关联数组都包装在单个键(缺省是‘data’)的关联数组中,它将成为各自模板中的对象名。您可以通过调用view对象的setTemplateVar()方法来改变这个变量。


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:

View类还有其它一些方法,在这里列出所有对配置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:https://github.com/liip/LiipHelloBundle/blob/master/Controller/HelloController.php

更多细节详见下列示例:https://github.com/liip/LiipHelloBundle/blob/master/Controller/HelloController.php

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'键,并包含一个表单

Then:

那么:

  • 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'发送到视图。


Configuration(配置)

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.

formats和templating_formats设置项确定了哪些格式分别被序列器和模板层支持。也就是说一些列在templating_formats中的格式将要求正在使用模板服务渲染的模板,而列在formats中的格式将使用序列器来渲染。上述两个设置值为false,则意味着禁用格式。


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.

当使用RouteRedirectView::create()时,对于html格式而言,将缺省启用强行重定向到路由的功能,但如果需要,其它格式缺省也将启用该功能。


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.

最终对应验证失败的缺省HTTP响应状态码为400.注意:当改变缺省值时您可以使用FOS\Rest\Util\Codes类中命名的常量,也可以使用整数状态码。


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

您也可以设置与缺省的twig模板引擎不同的缺省模板引擎:

# app/config/config.yml
fos_rest:
    view:
        formats:
            rss: true
            xml: false
        templating_formats:
            html: true
        force_redirects:
            html: true
        failed_validation: HTTP_BAD_REQUEST
        default_engine: twig

See the following example configuration for more details:https://github.com/liip-forks/symfony-standard/blob/techtalk/app/config/config.yml

更多细节请参见下列配置示例:https://github.com/liip-forks/symfony-standard/blob/techtalk/app/config/config.yml


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.

虽然许多事情应该可以通过序列化来解决,但在某些情况下它可能是不够的。举个例子,您可能需要在ViewHandler中执行一些自定义的逻辑。在这种情况下,您可能想要注册一个自定义处理器以处理一个特定的格式。自定义处理器可以通过自定义一个服务来注册,通过编译器发送。甚至还可以从控制器中的Action内部注册。

The callable will receive 3 parameters:

调用将接受3个参数:

  • 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:

注意在ViewHandler中有几个公共方法是有帮助的:

  • isFormatTemplating()

  • createResponse()

  • createRedirectResponse()

  • renderTemplate()

There is an example inside LiipHelloBundle to show how to register a custom handler:https://github.com/liip/LiipHelloBundle/blob/master/View/RSSViewHandler.php

https://github.com/liip/LiipHelloBundle/blob/master/Resources/config/config.yml

这是在LiipHelloBundle功能包内部的示例,用于展示如何注册自定义处理器:https://github.com/liip/LiipHelloBundle/blob/master/View/RSSViewHandler.php

https://github.com/liip/LiipHelloBundle/blob/master/Resources/config/config.yml


There is another example in Resources\doc\examples:https://github.com/FriendsOfSymfony/FOSRestBundle/blob/master/Resources/doc/examples/RssHandler.php

这是在Resources\doc\examples目录中的另一个示例:https://github.com/FriendsOfSymfony/FOSRestBundle/blob/master/Resources/doc/examples/RssHandler.php


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

下面的示例是在控制器Action中的注册:

<?php
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'];
                        unset($data['params']);
                    }
                    $view->setData($params);
                    $data['html'] = $handler->renderTemplate($view, 'html');
                    $view->setData($data);
                }
                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.

返回指南页或继续阅读监听器支持

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值