> Symfony中文手册 > 理解前端控制器、Kernel以及环境是如何一起工作的

理解前端控制器、Kernel以及环境是如何一起工作的

在如何掌握创建新环境一文中,讲解了“Symfony通过环境来配合不同的配置文件以运行你的程序”的基本知识。本节将深入解释当你的程序启动时到底发生了什么。为了能够打入到进程中,你需要理解以下“一起工作”的三个部分:

  • 前端控制器

  • Kernel类

  • 环境

通常,你不需要定义自己的前端控制器或是AppKernel.php类,因为Symfony标准版已经提供了合理的实现。

本文意在解释“程序背后”是怎么回事。

前端控制器 ¶

front controller前端控制器是一个很好的设计模式。它是一小段代码,可令所有 请求通过一个程序入口来执行。

在Symfony Standard Edition中,此项原则被app.php和app_dev.php两个文件用到,它们在web/目录下,是处理请求时最先执行的PHP脚本。

前端控制器的主要目的是创建一个AppKernel实例(紧跟着还要做点事),使它能处理请求并对浏览器返回相应的响应。

因为所有的请求都是通过前端控制器进入路由,因此前端控制器可以在“设置kernel”之前或是在“使用新功能decorate(装饰)内核”之前执行全局初始化。例如:

  • 配置自动加载器,或是添加附加的自动加载架构;
  • 通过把kernel和一个AppCache实例进行打包来添加Http级别的缓存;
  • 开启(或跳过)ClassCache
  • 开启Debug组件

下面这样的请求URL可以触发前端控制器:

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

如你所见,这个URL中包含了作为前端控制器而出现的PHP脚本名,你可以使用它来切换前端控制器,或者使用一个自定义的前端控制器,只需把脚本放到web/目录即可(如:app_cache.php)。

当使用Apache时,可以使用Symfony标准版内置的RewriteRule(重写规则),你可以从URL中去除那个脚本文件名,重写规则默认使用的是app.php

几乎所有web server都可以实现上面提到的这种“重写规则”之类似行为。查看你的服务器文档以了解细节,或者参考配置web服务器

应确保前端控制器足够安全,以防止非授权的访问。例如,你不希望在生产环境下向每一个用户提供可以使用的除错环境。

技术上讲,执行命令行时用到的bin/console脚本也是一个前端控制器,只是没有用在web上,而是用在对命令的“请求”上。

Kernel类 ¶

Kernel类是Symfony的核心。它负责设置“组成你的程序”的所有bundles,并向它们提供程序的配置信息。然后它会在处理请求之前,使用自己的handle()方法来创建服务容器。 method.

KernelInterface接口中声明的两个方法在Kernel 中未被填实,转而作为了template methods(模板方法):

registerBundles()
它必须返回“包含有程序所需的全部bundles”的一个数组。
registerContainerConfiguration()
它加载程序级配置信息。

为了填补这些小空缺,你的程序需要Kernel的子类来实现上述方法。也就是按照约定被称为AppKernel的这个类了。

再一次,Symfony标准版提供了一个AppKernel,位于app/目录下。这个类使用了环境名称——它被传入Kernel的constructor构造方法,可以通过getEnvironment()方法—— 来决定创建哪些bundles。此处的逻辑部分就在registerBundles()方法中完成,此方法供你在给自己的程序添加bundles时进行扩展。

当然你还可以自行创建你自己的“备选或附加”的AppKernel变量。所有你需要做的,就是使你的(或新增的)前端控制器能够利用好那个新kernel。

AppKernel的名称和位置并不固定。当把多个内核置于一个单一程序中时,可能“添加附加的子目录”是有意义的,例如app/admin/AdminKernel.phpapp/api/ApiKernel.php这种。所有问题的核心在于你的前端控制器要能创建出一个合适的kernel实例。

拥有不同的AppKernels也许在开启不同的前端控制器(潜在的不同服务器上的)以独立运行你程序的不同部分(例如,admin UI,the front-end UI以及database migrations)时是有用的。

还有很多AppKernel的使用场景,比如覆写默认的目录结构。然而通过对AppKernel完成一些具体实现,毋须像上面这样大动干戈的概率也很高。

环境 ¶

就像刚才提到的,AppKernel不得不去实现另外一个方法——registerContainerConfiguration()。这个方法负责从正确的环境中加载程序级配置信息。

Environments已经在前面章节中深度解析,你大概还记得Symfony标准版中有三种环境吧——dev, prodtest

更偏于技术的解释是,所有这些名字只不过就是从前端控制器传入AppKernel构造器的字符串。接下来这个名字会用于registerContainerConfiguration() 方法中以决定哪个配置文件将被加载。

Symfony标准版的AppKernel类通过引入app/config/config_*environment*.yml文件实现了这个方法。你当然也可以根据自己在加载配置信息时的复杂需要,以不同方式来填实这个方法。