The view layer makes it possible to write <code>format</code> (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等)与控制器无关。
In your controller action you will then need to create a <code>View</code> instance that is then passed to the <code>fos_rest.view_handler</code>service for processing. The <code>View</code> is somewhat modeled after the <code>Response</code> class, but as just stated it simply works as a container for all the data/configuration for the<code> ViewHandler</code> class for this particular action. So the <code>View</code> instance must always be processed by a <code>ViewHandler</code> (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控制器而言,只是扩展了一些便捷方式的控制器:
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
<code><?php</code>
<code>use</code> <code>FOS\RestBundle\Controller\FOSRestController;</code>
<code>class</code> <code>UsersController </code><code>extends</code> <code>FOSRestController</code>
<code>{</code>
<code> </code><code>public</code> <code>function</code> <code>getUsersAction()</code>
<code> </code><code>{</code>
<code> </code><code>$data</code> <code>= </code><code>// get data, in this case list of users.</code>
<code> </code><code>$view</code> <code>= </code><code>$this</code><code>->view(</code><code>$data</code><code>, 200)</code>
<code> </code><code>->setTemplate(</code><code>"MyBundle:Users:getUsers.html.twig"</code><code>)</code>
<code> </code><code>->setTemplateVar(</code><code>'users'</code><code>)</code>
<code> </code><code>;</code>
<code> </code><code>return</code> <code>$this</code><code>->handleView(</code><code>$view</code><code>);</code>
<code> </code><code>}</code>
<code> </code><code>public</code> <code>function</code> <code>redirectAction()</code>
<code> </code><code>$view</code> <code>= </code><code>$this</code><code>->redirectView(</code><code>$this</code><code>->generateUrl(</code><code>'some_route'</code><code>), 301);</code>
<code> </code><code>// or</code>
<code> </code><code>$view</code> <code>= </code><code>$this</code><code>->routeRedirectView(</code><code>'some_route'</code><code>, </code><code>array</code><code>(), 301);</code>
<code>}</code>
To simplify this even more: If you rely on the <code>ViewResponseListener</code> in combination withSensioFrameworkExtraBundle you can even omit the calls to <code>$this->handleView($view)</code>and directly return the view objects. See chapter 3 on listeners for more detailson the View Response Listener.
为了更简化:如果您依赖<code>ViewResponseListener</code>并结合SensioFrameworkExtraBundle功能包,您甚至可以忽略<code>$this->handleView($view)</code>的调用,而直接返回视图对象。更多细节请参见第3章节关于视图响应监听器的部分。
As the purpose is to create a format-agnostic controller, data assigned to the<code> View</code> instance should ideally be an object graph, though any data type is acceptable. Note that when rendering templating formats, the <code>ViewHandler</code> will wrap data types other than associative arrays in an associative array witha single key (default <code>'data'</code>), which will become the variable name of the object in the respective template. You can change this variable by callingthe <code>setTemplateVar()</code>method on the view object.
因为目标是创建与格式无关的控制器,所以指定给View实例的数据最好是一个对象图,虽然任何数据类型都可以被接受。注意,当渲染模板格式时,ViewHandler将数据类型以外的关联数组都包装在单个键(缺省是‘data’)的关联数组中,它将成为各自模板中的对象名。您可以通过调用view对象的setTemplateVar()方法来改变这个变量。
There are also two specialized <code>View</code> classes for handling redirects, one for redirecting to an URL called <code>RedirectView</code>and one to redirect to a route called <code>RouteRedirectView</code>. Note that whether these classes actually cause a redirector not is determined by the <code>force_redirects</code> configuration option,which is only enabled for <code>html</code> by default (see below).
这里也有两个指定的View类来处理重定向,一个是通过调用 RedirectView 来重定向到 URL,另一个是调用 RouteReirectView 来重定向到路由。注意这些类是否引发重定向是由配置选项force_redirects来决定的,该选项在缺省状态下仅对html生效。
There are several more methods on the <code>View</code> class, here is a list of all the important ones for configuring the view:
View类还有其它一些方法,在这里列出所有对配置View比较重要的方法:
<code>setData($data)</code> - Set the object graph or list of objects to serialize.
<code>setData($data)</code> - 设置要序列化的对象图或对象列表
<code>setHeader($name, $value)</code> - Set a header to put on the HTTP response.
<code>setHeader($name, $value)</code> - 设置HTTP响应头
<code>setHeaders(array $headers)</code> - Set multiple headers to put on the HTTP response.
<code>setHeaders(array $headers)</code> - 设置多个HTTP响应头
<code>setSerializationContext($context)</code> - 设置序列化上下文以便使用
<code>setTemplate($name)</code> - Name of the template to use in case of HTML rendering.
<code>setTemplate($name)</code> - 在HTML渲染时使用的模板名
<code>setTemplateVar($name)</code> - Name of the variable the data is in, when passed to HTML template. Defaults to <code>'data'</code>.
<code>setTemplateVar($name)</code> - 设置发送给HTML模板的数据变量名,缺省是<code>'data'</code>。
<code>setEngine($name)</code> - Name of the engine to render HTML template. Can be autodetected.
<code>setEngine($name)</code> - 渲染HTML模板引擎名,可自动匹配
<code>setFormat($format)</code> - The format the response is supposed to be rendered in. Can be autodetected using HTTP semantics.
<code>setFormat($format)</code> - 渲染响应时的格式,可以通过HTML语义自动匹配
<code>setLocation($location)</code> - The location to redirect to with a response.
<code>setLocation($location)</code> - 响应中重定向的位置
<code>setRoute($route)</code> - The route to redirect to with a response.
<code>setRoute($route)</code> - 响应中重定向的路由
<code>setResponse(Response $response)</code> - The response instance that is populated by the <code>ViewHandler</code>.
<code>setResponse(Response $response)</code> - 由ViewHandler填充的响应实例。
<a href="https://github.com/liip/LiipHelloBundle/blob/master/Controller/HelloController.php"></a>
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 <code>createView()</code> is called automatically.
在被渲染的模板中,表单将作为'form‘发送并自动调用createView()
<code>$form->getData()</code> is passed into the view as template as <code>'data'</code> if the form is the only view data.
如果表单只是视图数据的话,那么$form->getData()将作为模板,作为 'data'发送到视图。
The <code>formats</code> and <code>templating_formats</code> settings determine which formats are respectively supported by the serializer and by the template layer. In otherwords any format listed in <code>templating_formats</code> will require a template for rendering using the <code>templating</code> service, while any format listed in<code> formats</code> will use the serializer for rendering. For both settings avalue of <code>false</code> means that the given format is disabled.
formats和templating_formats设置项确定了哪些格式分别被序列器和模板层支持。也就是说一些列在templating_formats中的格式将要求正在使用模板服务渲染的模板,而列在formats中的格式将使用序列器来渲染。上述两个设置值为false,则意味着禁用格式。
When using <code>RouteRedirectView::create()</code> the default behavior of forcing a redirect to the route for html is enabled,but needs to be enabled for other formats if needed.
当使用<code>RouteRedirectView::create()</code>时,对于html格式而言,将缺省启用强行重定向到路由的功能,但如果需要,其它格式缺省也将启用该功能。
Finally the HTTP response status code for failed validation defaults to <code>400</code>. Note when changing the default you can use name constants of<code> FOS\Rest\Util\Codes</code> class or an integer status code.
最终对应验证失败的缺省HTTP响应状态码为400.注意:当改变缺省值时您可以使用<code>FOS\Rest\Util\Codes类中命名的常量,也可以使用整数状态码。</code>
You can also set the default templating engine to something different than the default of <code>twig</code>:
您也可以设置与缺省的twig模板引擎不同的缺省模板引擎:
<code># app/config/config.yml</code>
<code>fos_rest:</code>
<code> </code><code>view:</code>
<code> </code><code>formats:</code>
<code> </code><code>rss: </code><code>true</code>
<code> </code><code>xml: </code><code>false</code>
<code> </code><code>templating_formats:</code>
<code> </code><code>html: </code><code>true</code>
<code> </code><code>force_redirects:</code>
<code> </code><code>failed_validation: HTTP_BAD_REQUEST</code>
<code> </code><code>default_engine: twig</code>
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 <code>ViewHandler</code>. 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 <code>ViewHandler</code>
<code>ViewHandler实例</code>
the instance of the <code>View</code>
<code>View实例</code>
the instance of the <code>Request</code>
<code>Request实例</code>
Note there are several public methods on the <code>ViewHandler</code> which can be helpful:
注意在ViewHandler中有几个公共方法是有帮助的:
<code>isFormatTemplating()</code>
<code>createResponse()</code>
<code>createRedirectResponse()</code>
<code>renderTemplate()</code>
<a href="https://github.com/liip/LiipHelloBundle/blob/master/Resources/config/config.yml">https://github.com/liip/LiipHelloBundle/blob/master/Resources/config/config.yml</a>
Here is an example using a closure registered inside a Controller action:
下面的示例是在控制器Action中的注册:
22
23
24
25
26
27
28
29
30
31
32
<code>use</code> <code>Symfony\Bundle\FrameworkBundle\Controller\Controller;</code>
<code>use</code> <code>FOS\RestBundle\View\View;</code>
<code>class</code> <code>UsersController </code><code>extends</code> <code>Controller</code>
<code> </code><code>$view</code> <code>= View::create();</code>
<code> </code><code>...</code>
<code> </code><code>$handler</code> <code>= </code><code>$this</code><code>->get(</code><code>'fos_rest.view_handler'</code><code>);</code>
<code> </code><code>if</code> <code>(!</code><code>$handler</code><code>->isFormatTemplating(</code><code>$view</code><code>->getFormat())) {</code>
<code> </code><code>$templatingHandler</code> <code>= </code><code>function</code><code>(</code><code>$handler</code><code>, </code><code>$view</code><code>, </code><code>$request</code><code>) {</code>
<code> </code><code>// if a template is set, render it using the 'params' and place the content into the data</code>
<code> </code><code>if</code> <code>(</code><code>$view</code><code>->getTemplate()) {</code>
<code> </code><code>$data</code> <code>= </code><code>$view</code><code>->getData();</code>
<code> </code><code>if</code> <code>(</code><code>empty</code><code>(</code><code>$data</code><code>[</code><code>'params'</code><code>])) {</code>
<code> </code><code>$params</code> <code>= </code><code>array</code><code>();</code>
<code> </code><code>} </code><code>else</code> <code>{</code>
<code> </code><code>$params</code> <code>= </code><code>$data</code><code>[</code><code>'params'</code><code>];</code>
<code> </code><code>unset(</code><code>$data</code><code>[</code><code>'params'</code><code>]);</code>
<code> </code><code>}</code>
<code> </code><code>$view</code><code>->setData(</code><code>$params</code><code>);</code>
<code> </code><code>$data</code><code>[</code><code>'html'</code><code>] = </code><code>$handler</code><code>->renderTemplate(</code><code>$view</code><code>, </code><code>'html'</code><code>);</code>
<code> </code><code>$view</code><code>->setData(</code><code>$data</code><code>);</code>
<code> </code><code>}</code>
<code> </code><code>return</code> <code>$handler</code><code>->createResponse(</code><code>$view</code><code>, </code><code>$request</code><code>, </code><code>$format</code><code>);</code>
<code> </code><code>};</code>
<code> </code><code>$handler</code><code>->registerHandler(</code><code>$view</code><code>->getFormat(), </code><code>$templatingHandler</code><code>);</code>
<code> </code><code>}</code>
<code> </code><code>return</code> <code>$handler</code><code>->handle(</code><code>$view</code><code>);</code>
本文转自 firehare 51CTO博客,原文链接:http://blog.51cto.com/firehare/1250006,如需转载请自行联系原作者