drupal8文档_从请求到响应:Drupal 8内部之旅

drupal8文档

In the first article on Drupal 8 module development we looked a bit at the routing aspect of this process. We’ve seen that creating pages with paths is now a matter of declaring routes that match up with controllers. The latter, as we’ve seen, can return a render array that gets interpreted into markup and displayed in the main content area of that page. However, did you know that under the hood, Drupal actually transforms that array into a Response object according to the dictates of Symfony’s HTTPKernelInterface?

在有关Drupal 8模块开发的第一篇文章中,我们稍微了解了此过程的路由方面。 我们已经看到,创建带有路径的页面现在是声明与控制器匹配的路由的问题。 如我们所见,后者可以返回一个渲染数组,该渲染数组将被解释为标记并显示在该页面的主要内容区域中。 但是,您是否知道,Drupal实际上是根据Symfony的HTTPKernelInterface的指示将该数组转换为Response对象的?

drupal8wide

In this article, I would like us to go deeper into the internals of Drupal 8 (and Symfony2) and look at what actually happens (and can happen) from the moment a request is made by a user to the one in which they see something returned in response. The example I mentioned above is just one direction this process can go in, and today we are also going to see other possibilities. The goal is to understand the flexibility of the system which in turn can help us build awesome applications.

在本文中,我希望我们更深入地研究Drupal 8(和Symfony2)的内部结构,并查看从用户提出请求到他们看到某项请求的那一刻实际发生(可能发生)的情况。作为回应返回。 我上面提到的示例只是此过程可以进行的一个方向,而今天我们还将看到其他可能性。 目的是了解系统的灵活性,进而可以帮助我们构建出色的应用程序。

Before going into it, I strongly recommend you check out this diagram which does an amazing job at synthesizing what is often referred to as the render pipeline. Though in my opinion it represents more than the name implies because the render system is only part of what’s depicted, albeit a big one.

在深入研究之前,我强烈建议您检查一下该图 ,它在合成通常称为渲染管线的过程中起到惊人的作用。 尽管在我看来,它代表的含义远超过其名称所暗示的,因为渲染系统只是所描绘内容的一部分,尽管很大。

前端控制器(index.php) (Front controller (index.php))

It’s no secret that Symfony2 is now an important part of Drupal. The latter uses many of Symfony’s components, most importantly for this article the HTTPKernel and HTTPFoundation ones. Together they are responsible for encapsulating a user request, passing it to the application and then returning whatever comes back to the user in a consistent and OO way.

Symfony2现在已经成为Drupal的重要组成部分,这已不是什么秘密了。 后者使用了许多Symfony的组件,对于本文而言,最重要的是使用HTTPKernelHTTPFoundation的组件。 他们共同负责封装用户请求,将其传递给应用程序,然后以一致且面向对象的方式将返回的所有内容返回给用户。

The HTTPKernelInterface (something you probably heard about also from other contexts) is what glues all of this together by taking in a Request object and always returning a Response one. A very simple but powerful concept.

HTTPKernelInterface(您可能还从其他上下文中听说过 )通过接收一个Request对象并始终返回一个Response对象将所有这些粘合在一起。 一个非常简单但功能强大的概念。

This process is initiated inside the index.php file which starts by generating said Request object and passing it to the HTTPKernel::handle() method. The latter is then responsible for returning a Response object. At a high level, this is what happens both in a Drupal application as well as in a Symfony one (or any other that leverages the HTTPKernel component).

此过程在index.php文件中启动,该文件首先生成所述Request对象并将其传递给HTTPKernel::handle()方法。 然后,后者负责返回Response对象。 从高层次上讲,这是在Drupal应用程序和Symfony应用程序(或任何其他利用HTTPKernel组件的应用程序)中发生的。

HTTP内核和事件 (HTTPKernel and events)

HTTPKernel is the heart of any Symfony based application. Its handle() method, as we saw, has a great deal of responsibility in preparing a response and it does so in a workflow driven by events. This makes for a very flexible application where the heavy lifting is always delegated to listeners of these events.

HTTPKernel是任何基于Symfony的应用程序的心脏。 正如我们所看到的,它的handle()方法在准备响应中负有很多责任,并且它在由events驱动工作流中也是如此。 这使得应用程序非常灵活,始终将繁重的工作委托给这些事件的侦听器。

If you look at the diagram from earlier, you can see this workflow depicted in the second column, and it essentially represents the glue between Symfony and the Drupal side of things.

如果您看一下前面的图,您会看到第二栏中描述的该工作流程,它实质上代表了Symfony和事物的Drupal方面的纽带。

It starts with the first event called kernel.request. Subscribers to this event handle various tasks. But two very important ones in Drupal 8 are the format negotiation and routing. The first determines the type of response that needs to be returned (html, json, image, pdf, etc) while the second determines what the code responsible for handling this is (the _controller key of a route definition inside the routing.yml file). But like in most steps in this event workflow, if a listener returns a response object, the process skips most of the further steps (stops propagation) and goes straight to kernel.response.

它从第一个事件kernel.request 。 该事件的订阅者处理各种任务。 但是在Drupal 8中两个非常重要的方面是格式协商和路由。 第一个确定需要返回的响应类型(html,json,图像,pdf等),第二个确定负责处理该响应的代码( routing.yml文件中路由定义的_controller键) 。 但是,就像此事件工作流程中的大多数步骤一样,如果侦听器返回响应对象,则该过程将跳过大多数其他步骤(停止传播),并直接进入kernel.response

The second event is kernel.controller which is called after the application knows which controller is responsible for handling the request. At this point, listeners can still perform some overriding operations on it. Closely following this step, the Kernel is responsible for resolving the arguments that get passed to the controller. One such operation in Drupal is loading objects based on IDs found in the request (for example nodes) and directly providing the controller with them. Then finally the controller gets called with the respective parameters.

第二个事件是kernel.controller ,在应用程序知道哪个控制器负责处理请求后调用该事件。 此时,侦听器仍可以对其执行一些替代操作。 在紧接此步骤之后,内核负责解析传递给控制器​​的参数。 Drupal中的一种此类操作是根据在请求中找到的ID(例如节点)加载对象,然后直接向控制器提供对象。 然后最后使用相应的参数调用控制器。

The controller is responsible for returning a response of some kind. If it returns a Response object, the process skips to the kernel.response event. Listeners to the latter can perform last minute modifications on the object such as modifying headers or the content itself. And after getting it from the handle() method, the front controller uses the send() method on the Response object to send it back to the user and terminates the process.

控制器负责返回某种响应。 如果返回Response对象,则该过程将跳至kernel.response事件。 后者的侦听器可以在对象上执行最后一刻的修改,例如修改标头或内容本身。 从handle()方法获取它之后,前端控制器在Response对象上使用send()方法将其发送回用户并终止该过程。

symfony event workflow

更深入地介绍渲染数组 (Going deeper with render arrays)

If the controller does not return a Response object, the Kernel fires one last event: kernel.view. Its subscribers are responsible for turning the result of the controller into an actual Response object. So this means that you have the option of returning from your controller any kind of object as long as you couple it with a VIEW event subscriber that turns that into a proper Response.

如果控制器未返回Response对象,则内核将触发最后一个事件: kernel.view 。 其订户负责将控制器的结果转换为实际的Response对象。 因此,这意味着您可以选择从控制器返回任何类型的对象,只要将其与VIEW事件订阅者耦合即可将其转换为适当的Response

However, as we’ve seen in the example, most of the time controllers will return a render array. Usually this represents the page’s main content (similar to page callbacks in Drupal 7).

但是,正如我们在示例中看到的那样,大多数时间控制器将返回渲染数组。 通常,这代表页面的主要内容(类似于Drupal 7中的页面回调)。

To handle this, Drupal 8 has a MainContentViewSubscriber responsible for transforming this array into proper Response objects. It does so by using a particular MainContentRenderer chosen during the format negotiation phase we’ve talked about before. And although there are a few such renderers already available, the default one used is the HtmlRenderer.

为了解决这个问题,Drupal 8具有MainContentViewSubscriber,负责将此数组转换为适当的Response对象。 通过使用我们之前讨论过的格式协商阶段中选择的特定MainContentRenderer来实现。 尽管已经有一些这样的渲染器可用 ,但默认使用的是HtmlRenderer

HTMLRenderer (HTMLRenderer)

Since this is the most commonly used type of main content renderer, let’s go in a bit deeper and see how this builds the page.

由于这是最常用的主要内容呈现器类型,因此让我们更深入地了解一下如何构建页面。

One of the cool things about this step in the process is the concept of page variants. This means that HTMLRenderer dispatches an event responsible for finding out which type of page is to be used to wrap the main content render array: RenderEvents::SELECT_PAGE_DISPLAY_VARIANT. By default, the SimplePageVariant is used unless the Block module is enabled. In that case the BlockPageVariant kicks in and allows the placement of the blocks in the regions around the main content. If you want, you can subscribe to this event in your own module and provide your own variant.

页面变体的概念是这一过程中最酷的事情之一。 这意味着HTMLRenderer调度一个事件,该事件负责找出用于包装主要内容渲染数组的页面类型: RenderEvents::SELECT_PAGE_DISPLAY_VARIANT 。 默认情况下,除非启用了“阻止”模块,否则将使用SimplePageVariant 。 在那种情况下, BlockPageVariant会加入 ,并允许将块放置在主要内容周围的区域中。 如果需要,您可以在自己的模块中订阅此事件并提供自己的变体。

All of this happens within the prepare() method of the HTMLRenderer which supplies the renderResponse() method with a #type => 'page' render array that wraps the main content one. The latter two get in turn wrapped into a #type => 'html' render array which gets finally rendered using the Renderer class (the equivalent of drupal_render() in Drupal 7). The resulting HTML string gets added to the Response object and gets returned to the front controller.

所有这些都发生在HTMLRendererprepare()方法内,该方法为renderResponse()方法提供了#type => 'page'渲染数组,该数组将主要内容包装为一个。 后两个又被包装成一个#type => 'html'渲染数组,该数组最终使用Renderer渲染 (相当于Drupal 7中的drupal_render() )。 结果HTML字符串将添加到Response对象,并返回给前端控制器。

Although this is a very high level overview of the process, this is basically what happens. Now we have a Response object which means the Kernel can dispatch its kernel.response event. And right after this, the front controller can send the Response back to the user and terminate the process.

尽管这是该过程的非常高级的概述,但是基本上就是这样。 现在,我们有了一个Response对象,这意味着内核可以调度其kernel.response事件。 然后,前端控制器可以将Response发送回用户并终止该过程。

结论 (Conclusion)

In this article we’ve taken a journey into Drupal 8 (and Symfony2) internals by following the pipeline from a user request to the response the server returns. We’ve seen how Drupal 8 leverages the HTTPKernel and HTTPFoundation Symfony2 components and how it basically lives on top of them. Additionally, we’ve seen how the glue between them is made up of the events the Kernel dispatches to which Drupal subscribes for all of its functionality. Finally, we’ve seen how HTML pages are built and returned to the user with the help of the render pipeline.

在本文中,我们通过遵循从用户请求到服务器返回响应的管道,深入了Drupal 8(和Symfony2)内部。 我们已经看到了Drupal 8如何利用HTTPKernel和HTTPFoundation Symfony2组件以及它基本上如何生活在它们之上。 此外,我们已经看到了它们之间的粘合是如何由内核调度的事件组成的,Drupal为其预订了所有功能。 最后,我们已经了解了如何在渲染管道的帮助下构建HTML页面并将其返回给用户。

I believe that understanding what is going on under the hood in a Drupal 8 application will allow you to create awesome applications by knowing exactly which entry points you have into this flow. And I believe that if you take away only one thing from this article, it should be the word flexibility. Because the flexibility for building exactly what we need in Drupal 8 far surpasses anything in Drupal 7. It has truly become modern.

我相信,了解Drupal 8应用程序内幕的内容将使您能够确切地知道此流程中的入口点,从而创建出色的应用程序。 我相信,如果您仅从本文中删除一件事,那就应该是灵活性一词。 因为精确地构建我们在Drupal 8中所需的功能的灵活性远远超过了Drupal 7中的任何功能,所以它已经真正地变得现代了。

翻译自: https://www.sitepoint.com/from-request-to-response-a-journey-into-drupal-8-internals/

drupal8文档

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

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值