directory search
阅读前篇 简介 Yii 是什么 从 Yii 1.1 升级 入门 安装 Yii 运行应用 第一次问候 使用Forms 数据库应用 使用 Gii 生成代码 进阶 应用结构 概述 入口脚本 应用(Applications) 应用组件(Application Components) 控制器(Controllers) 模型(Models) 视图(views) 模块(Modules) 过滤器(Filters) 小部件(Widgets) 前端资源(Assets) 扩展(Extensions) 请求处理 运行概述 启动引导(Bootstrapping) 路由和创建URL 请求(Requests) 响应(Responses) Sessions 和 Cookies 错误处理(Handling Errors) 日志(Logging) 关键概念 组件(Component) 属性(Property) 事件(Events) 行为(Behaviors) 配置(Configurations) 别名(Aliases) 类自动加载(Autoloading) 服务定位器(Service Locator) 依赖注入容器(Dependency Injection Container) 配合数据库工作 数据库访问 (Data Access Objects) 查询生成器(Query Builder) 活动记录(Active Record) 数据库迁移(Migrations) Sphinx Redis MongoDB Elasticsearch 接收用户数据 创建表单(Creating Forms) 输入验证(Validating Input) 文件上传(Uploading Files) 收集列表输入(Collecting Tabular Input) 多模型的复合表单(Getting Data for Multiple Models) 显示数据 格式化输出数据(Data Formatting) 分页(Pagination) 排序(Sorting) 数据提供器(Data Providers) 数据小部件(Data Widgets) 客户端脚本使用(Working with Client Scripts) 主题(Theming) 安全 认证(Authentication) 授权(Authorization) 处理密码(Working with Passwords) 客户端认证(Auth Clients) 最佳安全实践(Best Practices) 缓存 概述 数据缓存 片段缓存 页面缓存 HTTP 缓存 RESTfull Web服务 快速入门(Quick Start) 资源(Resources) 控制器(Controllers) 路由(Routing) 格式化响应(Response Formatting) 授权认证(Authentication) 速率限制(Rate Limiting) 版本(Versioning) 错误处理(Error Handling) 开发工具 调试工具栏和调试器 使用Gii生成代码 生成API文档 测试 概述(Overview) 配置测试环境(Testing environment setup) 单元测试(Unit Tests) 功能测试(Function Tests) 验收测试(Acceptance Tests) 测试夹具(Fixtures) 高级专题 高级应用模板 创建自定义应用程序结构 控制台命令 核心验证器(Core Validators) 国际化 收发邮件 性能优化 共享主机环境 模板引擎 集成第三方代码 小部件 Bootstrap 小部件 Jquery UI 助手类 概述 Array 助手(ArrayHelper) Html 助手(Html) Url 助手(Url)
characters

应用主体

应用主体

应用主体是管理 Yii 应用系统整体结构和生命周期的对象。 每个Yii应用系统只能包含一个应用主体,应用主体在 入口脚本 中创建并能通过表达式 \Yii::$app 全局范围内访问。

补充: 当我们说"一个应用",它可能是一个应用主体对象,也可能是一个应用系统,是根据上下文来决定[译:中文为避免歧义,Application翻译为应用主体]。

Yii有两种应用主体: yii\web\Application and yii\console\Application, 如名称所示,前者主要处理网页请求,后者处理控制台请求。

应用主体配置

如下所示,当 入口脚本 创建了一个应用主体,它会加载一个 配置 文件并传给应用主体。

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的 配置文件 当中。

应用主体属性

应用主体配置文件中有许多重要的属性要配置,这些属性指定应用主体的运行环境。 比如,应用主体需要知道如何加载 控制器 ,临时文件保存到哪儿等等。 以下我们简述这些属性。

必要属性

在一个应用中,至少要配置2个属性: yii\base\Application::id 和 yii\base\Application::basePath。

yii\base\Application::id

yii\base\Application::id 属性用来区分其他应用的唯一标识ID。主要给程序使用。 为了方便协作,最好使用数字作为应用主体ID,但不强制要求为数字。

yii\base\Application::basePath

yii\base\Application::basePath 指定该应用的根目录。根目录包含应用系统所有受保护的源代码。 在根目录下可以看到对应MVC设计模式的modelsviewscontrollers等子目录。

可以使用路径或 路径别名 来在配置 yii\base\Application::basePath 属性。 两种格式所对应的目录都必须存在,否则系统会抛出一个异常。 系统会使用 realpath() 函数规范化配置的路径.

yii\base\Application::basePath 属性经常用于派生一些其他重要路径(如runtime路径),因此,系统预定义 @app 代表这个路径。 派生路径可以通过这个别名组成(如@app/runtime代表runtime的路径)。

重要属性

本小节所描述的属性通常需要设置,因为不同的应用属性不同。

yii\base\Application::aliases

该属性允许你用一个数组定义多个 别名。数组的key为别名名称,值为对应的路径。例如:

[
    'aliases' => [
        '@name1' => 'path/to/path1',
        '@name2' => 'path/to/path2',
    ],
]

使用这个属性来定义别名,代替 Yii::setAlias() 方法来设置。

yii\base\Application::bootstrap

这个属性很实用,它允许你用数组指定启动阶段yii\base\Application::bootstrap()需要运行的组件。 比如,如果你希望一个 模块 自定义URL 规则,你可以将模块ID加入到bootstrap数组中。

属性中的每个组件需要指定以下一项:

  • 应用 组件 ID.
  • 模块 ID.
  • 类名.
  • 配置数组.
  • 创建并返回一个组件的无名称函数.

例如:

[
    'bootstrap' => [
        // 应用组件ID或模块ID
        'demo',

        // 类名
        'app\components\Profiler',

        // 配置数组
        [
            'class' => 'app\components\Profiler',
            'level' => 3,
        ],

        // 无名称函数
        function () {
            return new app\components\Profiler();
        }
    ],
]

补充: 如果模块ID和应用组件ID同名,优先使用应用组件ID,如果你想用模块ID,可以使用如下无名称函数返回模块ID。 `php [

function () {
    return Yii::$app->getModule('user');
},

`

在启动阶段,每个组件都会实例化。如果组件类实现接口 yii\base\BootstrapInterface,也会调用 yii\base\BootstrapInterface::bootstrap() 方法。

举一个实际的例子,Basic Application Template 应用主体配置中, 开发环境下会在启动阶段运行 debug 和 gii 模块。

if (YII_ENV_DEV) {
    // configuration adjustments for 'dev' environment
    $config['bootstrap'][] = 'debug';
    $config['modules']['debug'] = 'yii\debug\Module';

    $config['bootstrap'][] = 'gii';
    $config['modules']['gii'] = 'yii\gii\Module';
}

注: 启动太多的组件会降低系统性能,因为每次请求都需要重新运行启动组件,因此谨慎配置启动组件。

yii\web\Application::catchAll

该属性仅 yii\web\Application 网页应用支持。 它指定一个要处理所有用户请求的 控制器方法,通常在维护模式下使用,同一个方法处理所有用户请求。

该配置为一个数组,第一项指定动作的路由,剩下的数组项(key-value 成对)指定传递给动作的参数,例如:

[
    'catchAll' => [
        'offline/notice',
        'param1' => 'value1',
        'param2' => 'value2',
    ],
]

yii\base\Application::components

这是最重要的属性,它允许你注册多个在其他地方使用的应用组件. 例如

[
    'components' => [
        'cache' => [
            'class' => 'yii\caching\FileCache',
        ],
        'user' => [
            'identityClass' => 'app\models\User',
            'enableAutoLogin' => true,
        ],
    ],
]

每一个应用组件指定一个key-value对的数组,key代表组件ID,value代表组件类名或 配置。

在应用中可以任意注册组件,并可以通过表达式 \Yii::$app->ComponentID 全局访问。

详情请阅读 应用组件 一节.

yii\base\Application::controllerMap

该属性允许你指定一个控制器ID到任意控制器类。Yii遵循一个默认的 规则指定控制器ID到任意控制器类(如post对应app\controllers\PostController)。 通过配置这个属性,可以打破这个默认规则,在下面的例子中,account对应到app\controllers\UserController, article 对应到 app\controllers\PostController

[
    'controllerMap' => [
        [
            'account' => 'app\controllers\UserController',
            'article' => [
                'class' => 'app\controllers\PostController',
                'enableCsrfValidation' => false,
            ],
        ],
    ],
]

数组的键代表控制器ID,数组的值代表对应的类名。

yii\base\Application::controllerNamespace

该属性指定控制器类默认的命名空间,默认为app\controllers。比如控制器ID为 post 默认对应 PostController (不带命名空间), 类全名为 app\controllers\PostController

控制器类文件可能放在这个命名空间对应目录的子目录下, 例如,控制器ID admin/post 对应的控制器类全名为app\controllers\admin\PostController

控制器类全面能被 自动加载,这点是非常重要的,控制器类的实际命名空间对应这个属性, 否则,访问时你会收到"Page Not Found"[译:页面找不到]。

如果你想打破上述的规则,可以配置 controllerMap 属性。

yii\base\Application::language

该属性指定应用展示给终端用户的语言,默认为 en 标识英文。如果需要之前其他语言可以配置该属性。

该属性影响各种 国际化 ,包括信息翻译、日期格式、数字格式等。 例如 yii\jui\DatePicker 小部件会根据该属性展示对应语言的日历以及日期格式。

推荐遵循 IETF language tag 来设置语言,例如 en 代表英文, en-US 代表英文(美国).

该属性的更多信息可参考 国际化 一节.

yii\base\Application::modules

该属性指定应用所包含的 模块。

该属性使用数组包含多个模块类 配置,数组的键为模块ID,例:

[
    'modules' => [
        // "booking" 模块以及对应的类
        'booking' => 'app\modules\booking\BookingModule',

        // "comment" 模块以及对应的配置数组
        'comment' => [
            'class' => 'app\modules\comment\CommentModule',
            'db' => 'db',
        ],
    ],
]

更多详情请参考 模块 一节。

yii\base\Application::name

该属性指定你可能想展示给终端用户的应用名称,不同于需要唯一性的 yii\base\Application::id 属性, 该属性可以不唯一,该属性用于显示应用的用途。

如果其他地方的代码没有用到,可以不配置该属性。

yii\base\Application::params

该属性为一个数组,指定可以全局访问的参数,代替程序中硬编码的数字和字符,应用中的参数定义到一个单独的文件并随时可以访问是一个好习惯。 例如用参数定义缩略图的长宽如下:

[
    'params' => [
        'thumbnail.size' => [128, 128],
    ],
]

然后简单的使用如下代码即可获取到你需要的长宽参数:

$size = \Yii::$app->params['thumbnail.size'];
$width = \Yii::$app->params['thumbnail.size'][0];

以后想修改缩略图长宽,只需要修改该参数而不需要相关的代码。

yii\base\Application::sourceLanguage

该属性指定应用代码的语言,默认为 'en-US' 标识英文(美国),如果应用不是英文请修改该属性。

和 语言 属性类似,配置该属性需遵循 IETF language tag. 例如 en 代表英文, en-US 代表英文(美国)。

该属性的更多信息可参考 国际化 一节.

yii\base\Application::timeZone

该属性提供一种方式修改PHP运行环境中的默认时区,配置该属性本质上就是调用PHP函数 date_default_timezone_set(),例如:

[
    'timeZone' => 'America/Los_Angeles',
]

yii\base\Application::version

该属性指定应用的版本,默认为'1.0',其他代码不使用的话可以不配置。

实用属性

本小节描述的属性不经常设置,通常使用系统默认值。如果你想改变默认值,可以配置这些属性。

yii\base\Application::charset

该属性指定应用使用的字符集,默认值为 'UTF-8',绝大部分应用都在使用,除非已有的系统大量使用非unicode数据才需要更改该属性。

yii\base\Application::defaultRoute

该属性指定未配置的请求的响应 路由 规则,路由规则可能包含模块ID,控制器ID,动作ID。 例如helppost/create,admin/post/create,如果动作ID没有指定,会使用yii\base\Controller::defaultAction中指定的默认值。

对于 yii\web\Application 网页应用,默认值为 'site' 对应 SiteController 控制器,并使用默认的动作。 因此你不带路由的访问应用,默认会显示 app\controllers\SiteController::actionIndex() 的结果。

对于 yii\console\Application 控制台应用, 默认值为 'help' 对应 yii\console\controllers\HelpController::actionIndex()。 因此,如果执行的命令不带参数,默认会显示帮助信息。

yii\base\Application::extensions

该属性用数组列表指定应用安装和使用的 扩展,默认使用@vendor/yiisoft/extensions.php文件返回的数组。 当你使用 Composer 安装扩展,extensions.php 会被自动生成和维护更新。 所以大多数情况下,不需要配置该属性。

特殊情况下你想自己手动维护扩展,可以参照如下配置该属性:

[
    'extensions' => [
        [
            'name' => 'extension name',
            'version' => 'version number',
            'bootstrap' => 'BootstrapClassName',  // 可选配,可为配置数组
            'alias' => [  // 可选配
                '@alias1' => 'to/path1',
                '@alias2' => 'to/path2',
            ],
        ],

        // ... 更多像上面的扩展 ...

    ],
]

如上所示,该属性包含一个扩展定义数组,每个扩展为一个包含 name 和 version 项的数组。 如果扩展要在 引导启动 阶段运行,需要配置 bootstrap以及对应的引导启动类名或 configuration 数组。 扩展也可以定义 别名

yii\base\Application::layout

该属性指定渲染 视图 默认使用的布局名字,默认值为 'main' 对应布局路径下的 main.php 文件, 如果 布局路径 和 视图路径 都是默认值,默认布局文件可以使用路径别名@app/views/layouts/main.php

如果不想设置默认布局文件,可以设置该属性为 false,这种做法比较罕见。

yii\base\Application::layoutPath

该属性指定查找布局文件的路径,默认值为 视图路径 下的 layouts 子目录。 如果 视图路径 使用默认值,默认的布局路径别名为@app/views/layouts

该属性需要配置成一个目录或 路径 别名。

yii\base\Application::runtimePath

该属性指定临时文件如日志文件、缓存文件等保存路径,默认值为带别名的 @app/runtime

可以配置该属性为一个目录或者路径 别名,注意应用运行时有对该路径的写入权限, 以及终端用户不能访问该路径因为临时文件可能包含一些敏感信息。

为了简化访问该路径,Yii预定义别名 @runtime 代表该路径。

yii\base\Application::viewPath

该路径指定视图文件的根目录,默认值为带别名的 @app/views,可以配置它为一个目录或者路径 别名.

yii\base\Application::vendorPath

该属性指定 Composer 管理的供应商路径,该路径包含应用使用的包括Yii框架在内的所有第三方库。 默认值为带别名的 @app/vendor 。

可以配置它为一个目录或者路径 别名,当你修改时,务必修改对应的 Composer 配置。

为了简化访问该路径,Yii预定义别名 @vendor 代表该路径。

yii\console\Application::enableCoreCommands

该属性仅 yii\console\Application 控制台应用支持, 用来指定是否启用Yii中的核心命令,默认值为 true

应用事件

应用在处理请求过程中会触发事件,可以在配置文件配置事件处理代码,如下所示:

[
    'on beforeRequest' => function ($event) {
        // ...
    },
]

on eventName 语法的用法在 Configurations 一节有详细描述.

另外,在应用主体实例化后,你可以在引导启动 阶段附加事件处理代码,例如:

\Yii::$app->on(\yii\base\Application::EVENT_BEFORE_REQUEST, function ($event) {
    // ...
});

yii\base\Application::EVENT_BEFORE_REQUEST

该事件在应用处理请求before之前,实际的事件名为 beforeRequest

在事件触发前,应用主体已经实例化并配置好了,所以通过事件机制将你的代码嵌入到请求处理过程中非常不错。 例如在事件处理中根据某些参数动态设置yii\base\Application::language语言属性。

yii\base\Application::EVENT_AFTER_REQUEST

该事件在应用处理请求after之后但在返回响应before之前触发,实际的事件名为afterRequest

该事件触发时,请求已经被处理完,可以做一些请求后处理或自定义响应。

注意 yii\web\Response 组件在发送响应给终端用户时也会触发一些事件,这些事件都在本事件after之后触发。

yii\base\Application::EVENT_BEFORE_ACTION

该事件在每个 控制器动作 运行before之前会被触发,实际的事件名为 beforeAction.

事件的参数为一个 yii\base\ActionEvent 实例, 事件处理中可以设置yii\base\ActionEvent::isValid 为 false 停止运行后续动作,例如:

[
    'on beforeAction' => function ($event) {
        if (some condition) {
            $event->isValid = false;
        } else {
        }
    },
]

注意 模块 和 控制器 都会触发 beforeAction 事件。 应用主体对象首先触发该事件,然后模块触发(如果存在模块),最后控制器触发。 任何一个事件处理中设置 yii\base\ActionEvent::isValid 设置为 false 会停止触发后面的事件。

yii\base\Application::EVENT_AFTER_ACTION

该事件在每个 控制器动作 运行after之后会被触发,实际的事件名为 afterAction.

该事件的参数为 yii\base\ActionEvent 实例,通过yii\base\ActionEvent::result属性, 事件处理可以访问和修改动作的结果。例如:

[
    'on afterAction' => function ($event) {
        if (some condition) {
            // 修改 $event->result
        } else {
        }
    },
]

注意 模块 和 控制器 都会触发 afterAction 事件。 这些对象的触发顺序和 beforeAction 相反,也就是说,控制器最先触发,然后是模块(如果有模块),最后为应用主体。

应用主体生命周期

当运行 入口脚本 处理请求时,应用主体会经历以下生命周期:

  1. 入口脚本加载应用主体配置数组。
  2. 入口脚本创建一个应用主体实例:
    • 调用 yii\base\Application::preInit() 配置几个高级别应用主体属性,比如yii\base\Application::basePath。
    • 注册 yii\base\Application::errorHandler 错误处理方法.
    • 配置应用主体属性.
    • 调用 yii\base\Application::init() 初始化,该函数会调用 yii\base\Application::bootstrap() 运行引导启动组件.
  3. 入口脚本调用 yii\base\Application::run() 运行应用主体:
    • 触发 yii\base\Application::EVENT_BEFORE_REQUEST 事件。
    • 处理请求:解析请求 路由 和相关参数;创建路由指定的模块、控制器和动作对应的类,并运行动作。
    • 触发 yii\base\Application::EVENT_AFTER_REQUEST 事件。
    • 发送响应到终端用户.
  4. 入口脚本接收应用主体传来的退出状态并完成请求的处理。
Previous article: Next article: