理解前端控制器、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.php
和app/api/ApiKernel.php
这种。所有问题的核心在于你的前端控制器要能创建出一个合适的kernel实例。
拥有不同的AppKernels
也许在开启不同的前端控制器(潜在的不同服务器上的)以独立运行你程序的不同部分(例如,admin UI,the front-end UI以及database migrations)时是有用的。
还有很多AppKernel
的使用场景,比如覆写默认的目录结构。然而通过对AppKernel
完成一些具体实现,毋须像上面这样大动干戈的概率也很高。
环境 ¶
就像刚才提到的,AppKernel
不得不去实现另外一个方法——registerContainerConfiguration()
。这个方法负责从正确的环境中加载程序级配置信息。
Environments已经在前面章节中深度解析,你大概还记得Symfony标准版中有三种环境吧——dev
, prod
和test
。
更偏于技术的解释是,所有这些名字只不过就是从前端控制器传入AppKernel
构造器的字符串。接下来这个名字会用于registerContainerConfiguration()
方法中以决定哪个配置文件将被加载。
Symfony标准版的AppKernel类通过引入app/config/config_*environment*.yml
文件实现了这个方法。你当然也可以根据自己在加载配置信息时的复杂需要,以不同方式来填实这个方法。