- 后端
- Web框架
【免费下载链接】yii2
Yii 2: The Fast, Secure and Professional PHP Framework
导读
在 Yii2 中,"应用(Application)"是掌管整个应用系统结构与生命周期的核心对象:每个 Yii 应用系统都拥有唯一一个应用对象,它由入口脚本创建,并全局暴露为\Yii::$app。本文以官方指南的《Приложения(应用)》一章为骨架,结合当前仓库的 framework/base/Application.php 等源码实现,系统讲解应用配置的加载方式、全部核心属性的含义与默认值、四类应用事件,以及从请求进入到响应返回的完整生命周期。读完本文,你将能够独立编写一份完整、正确的 Yii2 应用配置文件,并能利用事件钩子在合适的时机介入请求处理流程。
说明:语境中"应用"一词可能指应用对象(Application 实例),也可能指整个应用系统。本文默认指前者。
Yii2 共有两种应用类型:yii\web\Application(Web 应用,处理 HTTP 请求)与yii\console\Application(控制台应用,处理命令行命令)。二者均继承自抽象基类yii\base\Application,后者又继承自yii\base\Module,因此应用本身也是一个"模块",拥有模块的全部能力(控制器映射、子模块、事件等)。
应用配置(Application Configurations)
入口脚本在创建应用时,会加载一份配置并将其应用到应用对象上。以典型的 Web 入口脚本web/index.php为例:
require __DIR__ . '/../vendor/autoload.php'; require __DIR__ . '/../vendor/yiisoft/yii2/Yii.php'; // 加载应用配置 $config = require __DIR__ . '/../config/web.php'; // 创建应用对象并应用配置 (new yii\web\Application($config))->run();与普通配置一样,应用配置本质是一个"键值对"数组,用于初始化应用对象的各个属性。由于应用配置通常非常复杂,实践中会拆分为多个配置文件,例如上例中的web.php,还可能配合params.php、db.php等拆分文件。
从源码看,yii\base\Application的构造函数(framework/base/Application.php)会依次执行:
- 将自身注册为
Yii::$app全局单例; - 调用
preInit()预处理高优先级属性(如basePath); - 调用
registerErrorHandler()注册错误处理器; - 交给
Component::__construct()完成剩余属性的批量配置。
构造函数的注解明确要求:配置中必须同时包含id与basePath,否则会抛出InvalidConfigException。
控制台应用还有一个特殊能力:支持通过命令行--appconfig=path选项指定配置文件路径(见 framework/console/Application.php),若未指定则使用构造函数传入的配置。
应用属性(Application Properties)
应用属性描述了应用运行的环境,例如控制器如何加载、临时文件存放在哪里等。官方文档将它们划分为三组:必填属性、重要属性(因应用而异,通常需要配置)与有用属性(默认值符合惯例,仅在需要打破惯例时配置)。
必填属性
id
id是应用的唯一标识,主要用于程序内部区分不同应用(例如多模块、多应用场景)。虽然并非硬性要求,但为了最佳互操作性,官方建议只使用字母数字字符。
从源码看,preInit()(framework/base/Application.php)在$config['id']缺失时会直接抛出InvalidConfigException('The "id" configuration for the Application is required.')——这是硬性必填项。
basePath
basePath指定应用的根目录,它包含应用系统全部受保护的源代码,通常在其下可以看到models、views、controllers等对应 MVC 模式的子目录。
- 配置值可以是目录路径或路径别名,两种形式下目录都必须真实存在,否则抛异常;
- 路径会经
realpath()规范化; - 设置该属性会同时把路径别名
@app预定义为该目录(setBasePath()),因此可以用@app/runtime、@app/views等派生路径引用其下的子目录。
同样地,basePath缺失时preInit()也会抛出InvalidConfigException。
重要属性
aliases
允许在配置数组中批量定义别名,数组键为别名名(以@开头),值为对应路径:
[ 'aliases' => [ '@name1' => 'path/to/path1', '@name2' => 'path/to/path2', ], ]该属性存在的意义是:你可以在应用配置中定义别名,而无需逐个调用Yii::setAlias()。
bootstrap
这是非常实用的属性,用于指定一组应在应用引导(bootstrapping)过程中被加载的组件。例如,若希望某个模块在启动时定制 URL 规则,可以将其 ID 写入该属性。
每个元素支持以下五种格式:
components中定义的应用组件 ID;modules中定义的模块 ID;- 类名;
- 配置数组;
- 匿名函数(创建并返回组件)。
示例:
[ 'bootstrap' => [ // 应用组件 ID 或模块 ID 'demo', // 类名 'app\components\Profiler', // 配置数组 [ 'class' => 'app\components\Profiler', 'level' => 3, ], // 匿名函数 function () { return new app\components\Profiler(); } ], ]Info:如果某模块 ID 与应用组件 ID 相同,引导过程中将使用应用组件。若想使用模块,可用匿名函数显式指定:
[ function () { return Yii::$app->getModule('user'); }, ]
底层实现:bootstrap()方法(framework/base/Application.php)会依次实例化每个元素:闭包直接调用并取其返回值;字符串先尝试作为组件 ID($this->has())或模块 ID($this->hasModule())解析,若都不命中且不含\则抛InvalidConfigException("Unknown bootstrapping component ID: ...");其余情况通过Yii::createObject()创建。若组件类实现了yii\base\BootstrapInterface,还会调用其bootstrap()方法。
一个典型实战案例来自基础项目模板(Basic Project Template)的config/web.php——开发环境下将debug与gii模块注册为引导组件:
if (YII_ENV_DEV) { // 针对 'dev' 环境的配置调整 $config['bootstrap'][] = 'debug'; $config['modules']['debug'] = 'yii\debug\Module'; $config['bootstrap'][] = 'gii'; $config['modules']['gii'] = 'yii\gii\Module'; }Note:
bootstrap中放入过多组件会降低应用性能,因为每个请求都会加载同一批组件。请审慎使用引导组件。
catchAll(仅 Web 应用)
该属性仅受yii\web\Application支持(framework/web/Application.php)。它指定一个处理所有用户请求的控制器动作,主要用于维护模式(maintenance mode)下让所有请求统一走单个动作。
配置是一个数组:第一个元素是动作路由,其余键值对是传递给动作的参数:
[ 'catchAll' => [ 'offline/notice', 'param1' => 'value1', 'param2' => 'value2', ], ]底层实现:在handleRequest()(framework/web/Application.php)中,若catchAll非空,则不再通过$request->resolve()解析路由,而是直接用$route = $this->catchAll[0]并剥离其余参数作为动作参数。
Info:启用该属性后,开发环境下的 Debug 面板将无法工作。
components
这是最重要的属性,用于注册一组命名组件,即应用组件:
[ 'components' => [ 'cache' => [ 'class' => 'yii\caching\FileCache', ], 'user' => [ 'identityClass' => 'app\models\User', 'enableAutoLogin' => true, ], ], ]- 每个应用组件以键值对形式给出:键是组件 ID,值是该组件的类名或配置;
- 注册后可通过
\Yii::$app->componentID全局访问; - 更详细内容参见应用组件一节。
源码佐证:preInit()会把核心组件(coreComponents()返回的log、view、formatter、i18n、urlManager、assetManager、security,以及可选存在的mailer,见 framework/base/Application.php)合并进components配置,若自定义配置未指定class则自动补上默认类,保证内置组件开箱即用。
controllerMap
该属性允许把控制器 ID 映射到任意控制器类。默认情况下 Yii 依据controllerNamespace的约定进行映射(如 IDpost映射到app\controllers\PostController)。通过该属性可以打破约定。例如下面配置中,account映射到app\controllers\UserController,article映射到app\controllers\PostController:
[ 'controllerMap' => [ 'account' => 'app\controllers\UserController', 'article' => [ 'class' => 'app\controllers\PostController', 'enableCsrfValidation' => false, ], ], ]键是控制器 ID,值是控制器类的全限定类名或配置。controllerMap属性本身定义在基类yii\base\Module中(framework/base/Module.php)。
controllerNamespace
该属性指定控制器类默认所在的命名空间,默认值为app\controllers。若控制器 ID 为post,按约定控制器类名(不含命名空间)为PostController,全限定类名即为app\controllers\PostController(对应属性默认值见 framework/base/Application.php)。
- 控制器类也可位于该命名空间对应目录的子目录中,例如 ID
admin/post对应全限定类名app\controllers\admin\PostController; - 必须保证控制器类的全限定类名可被自动加载,且其实际命名空间与该属性一致,否则访问应用时会得到 "Страница не найдена"(页面未找到)错误;
- 如需打破约定,请配置 controllerMap。
language
该属性指定应用向最终用户展示内容的语言,默认值为en(英语)。如需支持多语言,必须配置此项。
它决定了国际化的多个方面:消息翻译、日期格式化、数字格式化等。例如yii\jui\DatePicker部件默认用它决定日历显示语言与日期格式。
官方建议使用 [IETF 语言标签] 规范书写,如en表示英语、en-US表示美国英语。注意源码中的默认值实际为'en-US'(见 framework/base/Application.php),即文档所说默认en与实际代码存在细微差异,配置时建议显式指定。更多细节见国际化章节。
modules
该属性指定应用包含的模块。值为模块类或配置的数组,键为模块 ID:
[ 'modules' => [ // 以模块类指定 "booking" 模块 'booking' => 'app\modules\booking\BookingModule', // 以配置数组指定 "comment" 模块 'comment' => [ 'class' => 'app\modules\comment\CommentModule', 'db' => 'db', ], ], ]更多细节见模块章节。
name
应用的显示名称,可展示给最终用户。与必须唯一的id不同,name主要用于展示,无需唯一。若代码未使用该属性,则无需配置。源码默认值为'My Application'(framework/base/Application.php)。
params
该属性指定一组全局可访问的应用参数。与其在代码各处硬编码数字和字符串,不如在配置中统一声明为参数再按需引用。例如定义图片缩略图尺寸:
[ 'params' => [ 'thumbnail.size' => [128, 128], ], ]在代码中使用:
$size = \Yii::$app->params['thumbnail.size']; $width = \Yii::$app->params['thumbnail.size'][0];日后需要调整缩略图尺寸时,只需修改应用配置,无需触碰任何依赖代码。
sourceLanguage
该属性指定应用代码本身的书写语言,默认值为'en-US'(美国英语)。若代码中的文本内容不是英语,则应相应配置。与language一样,建议使用 [IETF 语言标签] 规范书写。更多细节见国际化章节。
timeZone
该属性是设置 PHP 运行时默认时区的另一种方式。配置该属性本质上等价于调用 PHP 函数date_default_timezone_set()。例如:
[ // 欧洲/莫斯科(译者注) 'timeZone' => 'America/Los_Angeles', ]源码佐证:setTimeZone()(framework/base/Application.php)内部就是一行date_default_timezone_set($value)。同时preInit()在php.ini未配置date.timezone时会回退设置为UTC(见 framework/base/Application.php)。
version
应用的版本号,默认值为'1.0'。若代码未使用它,则无需配置。
有用属性
charset
应用使用的字符编码,默认'UTF-8'。对绝大多数应用应保持默认,除非在处理包含大量非 Unicode 数据的遗留系统时。
defaultRoute
指定当请求未指定路由时应用使用的默认路由。路由可包含子模块 ID、控制器 ID 与/或动作 ID,例如help、post/create、admin/post/create。若未给出动作 ID,则使用yii\base\Controller::defaultAction指定的默认值。
- Web 应用:默认值为
'site'(framework/web/Application.php),即使用SiteController及其默认动作。因此不带路由访问应用时,展示的是app\controllers\SiteController::actionIndex()的结果; - 控制台应用:默认值为
'help'(framework/console/Application.php),即内置命令yii\console\controllers\HelpController::actionIndex()。因此不带任何参数执行yii时会显示帮助信息。
extensions
该属性指定应用安装并使用的扩展列表。默认情况下其值为@vendor/yiisoft/extensions.php返回的数组;该文件由 Composer 在安装扩展时自动生成与维护,因此绝大多数情况无需配置。
特殊场景下手动维护扩展时可这样配置:
[ 'extensions' => [ [ 'name' => 'extension name', 'version' => 'version number', 'bootstrap' => 'BootstrapClassName', // 可选,也可以是配置数组 'alias' => [ // 可选 '@alias1' => 'to/path1', '@alias2' => 'to/path2', ], ], // ... 其余扩展同理 ... ], ]属性值为扩展规范数组,每个扩展至少包含name与version。若扩展需要在引导过程中运行,可指定bootstrap元素(引导类名或配置数组);扩展还可定义若干别名。
源码佐证:bootstrap()方法在$this->extensions === null时会自动加载@vendor/yiisoft/extensions.php,随后先为每个扩展注册alias,再实例化bootstrap元素并判断是否实现BootstrapInterface(见 framework/base/Application.php)。
layout
指定渲染视图时使用的默认布局名,默认值为'main',即使用布局目录(见下文 layoutPath)下的main.php。若布局目录与视图目录均为默认值,则默认布局文件可表示为别名@app/views/layouts/main.php。
如需默认禁用布局,可设为false(非常少见)。
layoutPath
指定查找布局文件的路径,默认值为视图目录(见下文 viewPath)下的layouts子目录。视图目录取默认值时,默认布局路径为@app/views/layouts。可配置为目录或路径别名。
runtimePath
指定存放临时文件(如日志文件、缓存文件)的路径,默认值为别名@app/runtime对应的目录。
- 可配置为目录或路径别名;
- 该目录必须对运行应用的进程可写;
- 目录应防止最终用户访问,因为其中临时文件可能含敏感信息;
- Yii 为此预定义了别名
@runtime。
源码佐证:setRuntimePath()在设置路径的同时会注册@runtime别名(framework/base/Application.php);getRuntimePath()未设置时默认取basePath/runtime(framework/base/Application.php)。
viewPath
指定视图文件的根目录,默认值为别名@app/views对应的目录。可配置为目录或路径别名。
vendorPath
指定由 Composer 管理的第三方库目录,包含应用使用的全部第三方库(含 Yii 框架本身),默认值为别名@app/vendor对应的目录。
- 可配置为目录或路径别名;
- 修改该属性时,务必同步调整 Composer 配置;
- Yii 为此预定义了别名
@vendor。
源码佐证:setVendorPath()在设置路径时会同时注册@vendor、@bower与@npm三个别名(framework/base/Application.php);getVendorPath()未设置时默认取basePath/vendor。
enableCoreCommands(仅控制台应用)
该属性仅受yii\console\Application支持,指定是否启用 Yii 内置的核心控制台命令,默认值为true(framework/console/Application.php)。
源码佐证:init()中若enableCoreCommands为真,会把coreCommands()返回的内置命令注册进controllerMap(若未被覆盖);随后无论如何都会确保help命令存在(framework/console/Application.php)。
应用事件(Application Events)
应用在处理请求的生命周期中会触发多个事件,可在应用配置中以on eventName语法挂载处理器:
[ 'on beforeRequest' => function ($event) { // ... }, ]on eventName语法详见配置一章。也可以在应用对象创建后的引导过程中动态挂载,例如:
\Yii::$app->on(\yii\base\Application::EVENT_BEFORE_REQUEST, function ($event) { // ... });四个事件常量定义在 framework/base/Application.php 与 framework/base/Module.php 中。
EVENT_BEFORE_REQUEST(事件名beforeRequest)
在应用开始处理请求之前触发。触发时应用对象已被配置并初始化,因此非常适合通过事件机制插入自定义代码来拦截请求处理流程。例如,处理器可根据某些参数动态设置language属性。
EVENT_AFTER_REQUEST(事件名afterRequest)
在应用完成请求处理之后、发送响应之前触发。此时请求处理已结束,可借此机会对请求做后处理或定制响应。
注意:response组件在向用户发送内容时也会触发自己的事件,这些事件发生在该事件之后。
EVENT_BEFORE_ACTION(事件名beforeAction)
在每个控制器动作执行之前触发。事件参数是yii\base\ActionEvent实例,处理器可将$event->isValid设为false以阻止动作执行。例如:
[ 'on beforeAction' => function ($event) { if (некоторое условие) { $event->isValid = false; } else { } }, ]同名beforeAction事件也会在模块和控制器上触发,触发顺序为:应用最先 → 模块(若有)→ 控制器最后。一旦某个处理器将isValid设为false,后续所有事件都不会再触发。
EVENT_AFTER_ACTION(事件名afterAction)
在每个控制器动作执行之后触发。事件参数同样是yii\base\ActionEvent,通过$event->result可访问或修改动作的执行结果。例如:
[ 'on afterAction' => function ($event) { if (некоторое условие) { // 处理 $event->result } else { } }, ]同名afterAction也会在模块与控制器上触发,但其顺序与beforeAction相反:控制器最先 → 模块(若有)→ 应用最后。
应用生命周期(Application Lifecycle)
当入口脚本被执行为处理某个请求时,应用将经历如下生命周期:
- 入口脚本将应用配置作为数组加载;
- 入口脚本创建新的应用对象:
- 调用
preInit(),配置高优先级属性,如basePath(还会处理vendorPath、runtimePath、timeZone、container,并把核心组件合并进components); - 注册错误处理器(
errorHandler组件,见registerErrorHandler(),framework/base/Application.php); - 配置应用其余属性;
- 调用
init(),后者进一步调用bootstrap()运行引导组件(含扩展的引导项与bootstrap属性中的组件);
- 调用
- 入口脚本调用
run()运行应用(framework/base/Application.php):- 触发
EVENT_BEFORE_REQUEST事件; - 处理请求:把请求信息解析为路由及关联参数;按路由创建模块、控制器与动作对象;执行动作;
- 触发
EVENT_AFTER_REQUEST事件; - 将响应发送给最终用户;
- 触发
- 入口脚本从应用获取退出状态码,结束请求处理。
run()的源码完整印证了这一过程:它通过$this->state依次经历STATE_BEFORE_REQUEST→STATE_HANDLING_REQUEST→STATE_AFTER_REQUEST→STATE_SENDING_RESPONSE→STATE_END五种状态,并在对应节点触发事件、调用抽象方法handleRequest()与$response->send()(各状态常量见 framework/base/Application.php)。
此外,Web 应用在bootstrap()阶段还会额外注册@webroot(入口脚本所在目录)与@web(基础 URL)两个别名(framework/web/Application.php),这也是 Web 与控制台应用引导差异的体现。
小结与延伸阅读
应用对象是 Yii2 应用系统的"总开关":配置决定了它如何加载控制器、存储临时文件、解析路由与国际化;事件提供了在请求前、请求后、动作前、动作后四个关键节点介入的机会;生命周期则完整串联了从入口脚本创建对象到响应发送的每一步。
- 更深入了解配置语法:概念:配置
- 应用组件注册与访问:应用组件
- 路径别名机制:概念:别名
- 引导组件执行细节:运行时引导
- 模块组织方式:模块
- 入口脚本职责:入口脚本
- 源码参考:framework/base/Application.php、framework/web/Application.php、framework/console/Application.php、framework/base/Module.php
- 后端
- Web框架
【免费下载链接】yii2
Yii 2: The Fast, Secure and Professional PHP Framework
相关推荐
Yii 2 应用(Application)完全指南:配置、属性、事件与生命周期解析
Yii 2 应用(Application)完全指南:配置、属性、事件与生命周期解析 应用(Application)对象是 Yii 2 框架中统领整个应用结构(M
后端Web框架3种实例化渲染方案对比:OpenGL-Examples性能优化指南
3种实例化渲染方案对比:OpenGL Examples性能优化指南 OpenGL Examples是一个专注于提供简单单文件OpenGL示例的项目,通过实例化渲
后端Web框架Emscripten Module 对象完全指南:从属性配置到运行时生命周期控制
Emscripten Module 对象完全指南:从属性配置到运行时生命周期控制 Module 是 Emscripten 生成的 JavaScript 中一个全
编译器WebAssembly开发工具构建工具
创作声明:本文部分内容由AI辅助生成(AIGC),仅供参考