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,如需轉載請自行聯系原作者