首页
Yii2 应用结构说明

入口脚本(Entry Scripts)

使用 ./yii 初始化应用,应用入口分为 web 应用和 控制台应用:

web 应用

/frontend/web/index.php

<?php
defined('YII_DEBUG') or define('YII_DEBUG', true);
defined('YII_ENV') or define('YII_ENV', 'dev');

// 注册 Composer 自动加载器
require __DIR__ . '/../vendor/autoload.php';
// 包含 Yii 类文件
require __DIR__ . '/../vendor/yiisoft/yii2/Yii.php';
// 加载应用配置
$config = require __DIR__ . '/../config/web.php';
// 创建、配置、运行一个应用
(new yii\web\Application($config))->run();

控制台应用:

yii.php

#!/usr/bin/env php
<?php
/**
 * Yii console bootstrap file.
 *
 * @link https://www.yiiframework.com/
 * @copyright Copyright (c) 2008 Yii Software LLC
 * @license https://www.yiiframework.com/license/
 */

defined('YII_DEBUG') or define('YII_DEBUG', true);
defined('YII_ENV') or define('YII_ENV', 'dev');

// 注册 Composer 自动加载器
require __DIR__ . '/vendor/autoload.php';

// 包含 Yii 类文件
require __DIR__ . '/vendor/yiisoft/yii2/Yii.php';

// 加载应用配置
$config = require __DIR__ . '/config/console.php';

$application = new yii\console\Application($config);
$exitCode = $application->run();
exit($exitCode);

常量定义

有两种方式定义,

  • params.php中定义,然后使用\Yii::$app->params["adminEmail"]获取

  • 自己新建一个constants.php文件,然后在入口文件中引入

common/config/constants.php

<?php
const STATUS_INACTIVE = 0;
const STATUS_ACTIVE = 1;

入口文件最好使用environments里面的,为每个环境都加上,因为后面使用./init的时候都是根据这里的文件来生成对应的环境文件。

environments/dev/frontend/web/index.php
// 常量文件
require __DIR__ . '/../../common/config/constants.php';

environments/dev/yii
// 常量文件
require __DIR__ . '/common/config/constants.php';

环境常量(Environment Constants)

应用(Applications)

模块

https://www.yiiframework.com/doc/guide/2.0/zh-cn/structure-modules

模块是独立的软件单元,由模型,视图,控制器和其他支持组件组成,终端用户可以访问在应用主体中已安装的模块的控制器。

模块被当成小应用主体来看待,和应用主体不同的是,模块不能单独部署,必须属于某个应用主体。

模块可以作为 DDD 的不同域来玩,作为一个聚合根使用。

模块需要在应用的主体配置中添加后才能使用:

frontend/config/main.php

[
    'modules' => [
        'forum' => [
            'class' => 'app\modules\forum\Module',
            // ... 模块其他配置 ...
        ],
    ],
]

模块中加载配置

模块可以有自己的配置文件,在Module.phpinit函数中,可以加载自己的配置文件:

public function init() {
	parent::init();
	// 从config.php 加载配置来初始化模块
	\Yii::configure($this , require __DIR__ . '/config/main.php');
}

然后再建立一个自己的配置文件,里面的内容跟应用里的一样:

frontend/modules/accounts/config/main.php

<?php
return [
	'components' => [
		// list of component configurations
	] ,
	'params' => [
		// list of parameters
	] ,
	'as action-time-filter' => [
		'class' => frontend\modules\accounts\filters\ActionTimeFIlter::class ,
		'only' => ['accounts/index']
	] ,
];

过滤器

https://www.yiiframework.com/doc/guide/2.0/zh-cn/structure-filters

使用过滤器可以实现 AOP 编程。

自定义过滤器的使用

创建一个过滤器。可以创建在 modules 里面,或者整个应用层次。

frontend\modules\accounts\filters\ActionTimeFilter.php

<?php


namespace frontend\modules\accounts\filters;

use Yii;
use yii\base\ActionFilter;

/**
 * 申明一个记录动作执行时间日志的过滤器
 * Class ActionTimeFilter
 */
class ActionTimeFilter extends ActionFilter
{
	private $_startTime;

	public function beforeAction($action) {
        $this->_startTime = microtime(TRUE);
        return parent::beforeAction($action); // TODO: Change the autogenerated stub
	}

	public function afterAction($action , $result) {
		$time = microtime(TRUE) - $this->_startTime;
		Yii::debug("Action '{$action->uniqueId}' spent $time second.");
		YII::error('我是一条错误');
		print_r("会走");
		return parent::afterAction($action , $result); // TODO: Change the autogenerated stub
	}
}

注意:自己实现的过滤器最后要返回父类的动作,不然有问题。

return parent::beforeAction($action);

过滤器分为 预过滤(beforeAction)和后过滤(afterAction),可以理解为前置处理器和后置处理器。

当一个动作有多个过滤器时,根据以下规则先后执行:

预过滤

按顺序执行应用主体中 behaviors() 列出的过滤器。
按顺序执行模块中 behaviors() 列出的过滤器。
按顺序执行控制器中 behaviors() 列出的过滤器。
如果任意过滤器终止动作执行, 后面的过滤器(包括预过滤和后过滤)不再执行。
成功通过预过滤后执行动作。

后过滤

倒序执行控制器中 behaviors() 列出的过滤器。
倒序执行模块中 behaviors() 列出的过滤器。
倒序执行应用主体中 behaviors() 列出的过滤器。

使用过滤器

可以在控制器、模块或应用主体 中申明过滤器

申明之后,过滤器会应用到所属该模块或应用主体的 所有 控制器动作, 除非配置过滤器的 only 和 except 属性。

控制器中使用

public function behaviors() {
	return [
		[
			'class' => 'frontend\modules\accounts\filters\ActionTimeFilter' ,
			// 只有 index 和 user Action 会执行该过滤器
			'only' => ['index' , 'user'],
			// delete 方法不会执行该过滤器
			'expect'=> ['delete']
		]
	];
}

应用中使用

应用或 modules 中如果要使用 only 属性,这里需要用路由的方式执行动作。

frontend/config/main.php

'as main-app-filter' => [
	'class' => frontend\filters\MainAppFilter::class ,
	'only' => ['accounts/accounts/index']
],

modules 中使用

modules 中使用,需要注意的是:only的路由跟应用里是不一样的,这里少了一个accounts,因为当前就是在accounts这个模块里面

frontend/modules/accounts/config/main.php

'as main-app-filter' => [
    'class' => frontend\filters\MainAppFilter::class ,
    'only' => ['accounts/accounts/index']
],