离线下载
PDF版 ePub版

极客学院团队出品 · 更新于 2018-11-28 11:00:43

理解前端控制器、内核及环境如何协同工作

如何掌握并创建新的环境这一节中我们解释了 Symfony 如何在不同的配置之下使用环境来运行的应用程序的基本思想。这一节我们将会更加深入地介绍当你的应用程序自我启动时会发生什么。为了理解这一过程,你必须理解一起运行的三个部分:

通常情况下,你不需要定义你自己的前端控制器或者 AppKernel 类由于 Symfony 的标准版本提供了默认的安装设置。

这一节的文档就是来解释表象之后发生的事情的。

前端控制器

前端控制器是人们所熟知的设计样式;它是由一些应用程序运行的代码的所有请求形成的代码组成的。

Symfony 的标准版本中,这个角色被 web/ 目录下的 app.phpapp_dev.php 文件所取代。这些是当一个请求被处理时最先执行的 PHP 脚本。

前端控制器的主要目的就是创建一个 AppKernel 的实例(稍后再作更多的介绍),使得它可以处理请求并且向浏览器返回处理结果。

由于每一个请求都是经过它按路径发送的,前端控制器可以被用来全局的优先初始化来建立 kernel 或者使用附加特征装饰 kernel。例子包括:

  • 设置自动加载或者添加自动加载机制;
  • 通过使用 AppCache 的实例封装添加 HTTP 层的缓存;
  • 启用(或者跳过)ClassCache
  • 启用 Debug Component

前端控制器可能被请求链接地址选择,就像下面所示:

http://localhost/app_dev.php/some/path/...

正如你所见,这个链接包含了用来作为前端控制器的 PHP 脚本。你可以用它轻松地切换前端控制器或者使用一个放置在 web/ 目录中的定制的控制器(例如 app_cache.php)。

当使用 Apache 以及由 Symfony 的标准版本所定义的 RewriteRule 时,你可以忽略链接中的文件名并且 RewriteRule 会将 app.php 作为默认的。

基本上每一个其它的网页服务器都应该可以表现出一种和上面描述的 RewriteRule 相似的行为。阅读你的服务器文档查看更多细节或者可以看配置网页服务器

确保你的前端控制器不被未授权访问。举例来说,你不想对于任意你的生产环境的用户都开放调试模式。

从技术层面来讲,在命令行运行 Symfony 时使用的 app/console 脚本也是前端控制器,只是不是为网页应用,而是命令行请求。

Kernel 类

Kernel 类是 Symfony 的核心。它负责建立组成你的应用程序的所有 bundle,并且向它们提供应用程序的设置。然后它用它的 [handle()](http://api.symfony.com/2.7/Symfony/Component/HttpKernel/HttpKernelInterface.html#handle()) 方法在服务请求之前创建服务容器。

KernelInterface 中声明了在 Kernel 没有应用的两种方法并且因此将它们作为模板方法提供。

[registerBundles()](http://api.symfony.com/2.7/Symfony/Component/HttpKernel/KernelInterface.html#registerBundles())
它必须返回一批运行应用程序所需要的所有 bundle。

[registerContainerConfiguration()](http://api.symfony.com/2.7/Symfony/Component/HttpKernel/KernelInterface.html#registerContainerConfiguration())
它负责加载应用程序配置。

为了填补这些(小的)空白,你的应用程序需要把 Kernel 划为子类并且实现这些方法。按照惯例结果类叫做 AppKernel

除此之外,Symfony 标准版本在 app/ 目录下提供了 AppKernel。这个类是使用了环境的名称——环境的名称是传给 Kernel 的 [constructor](http://api.symfony.com/2.7/Symfony/Component/HttpKernel/Kernel.html#__construct()) 方法以及可以使用 [getEnvironment()](http://api.symfony.com/2.7/Symfony/Component/HttpKernel/Kernel.html#getEnvironment()) 方法获得的——来决定创建哪个 bundle。这个的逻辑是在 registerBundles() 中,当你向你的应用程序中添加 bundle 时意味着你在扩展方法。

当然,你也可以自己创建,有选择性的或者附加的 AppKernel 不同版本。你所需要的就是适应(或者添加新的)前端控制器并且会使用新的 Kernel。

AppKernel 的名称和位置不能修复。当将多个 Kernel 放入一个简单的应用程序中时,这也许会使得添加附加的子目录变得有意义,举例来说 app/admin/AdminKernel.phpapp/api/ApiKernel.php。所有这些重要的就是你的前端控制器可以创建适当的 kernel 实例。

拥有不同的 AppKernels 可能会对于启用不同的前端控制器(可能在不同的服务器上)来独立运行你的应用程序的部分很有用(举例来说,admin UI, front-end UI 和数据库迁移)。

AppKernel 还可以干很多事,例如重写默认目录结构。但是你实施几个 AppKernel 不需要像这样忙忙碌碌改变的几率是很高的。

环境

就像刚才提到的,AppKernel 必须要调用其它方法——[registerContainerConfiguration()](http://api.symfony.com/2.7/Symfony/Component/HttpKernel/KernelInterface.html#registerContainerConfiguration())。这个方法是从正确的*环境*中加载应用程序的设置的

环境已经在前面的章节中详细介绍过了,你可能也记得 Standard 标准版本有三种环境——dev, prodtest

更技术的讲,这些名称只不过是从前端控制器传递到 AppKernel 的构造器的字符串。这个名称之后可以应用在 [registerContainerConfiguration()](http://api.symfony.com/2.7/Symfony/Component/HttpKernel/KernelInterface.html#registerContainerConfiguration()) 方法中来决定加载哪个文件。

Symfony 标准版本中的 AppKernel 类只是简单地通过加载 app/config/config_environment.yml 文件来实施这个方法。当然,你如果需要更加精确的加载你的应用程序的方法的话也可以区别地使用这个方法。