自定义 Gii 模板

开发是需要用到 gii,但是 gii 并不是完全符合自己的开发需求,所以需要对他做一点改造

这里先拿 basic 版举例, advance版同理

1.修改配置文件 web.php

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
// file path: @app/config/web.php

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

$config['bootstrap'][] = 'gii';
$config['modules']['gii'] = [
'class' => 'yii\gii\Module',
// 这里把原来的 model generator 给覆盖成自己的
'generators' => [
'model' => [
// 自定义的模板生成器
'class' => 'app\common\gii\model\Generator',
//设置我们自己的模板
'templates' => [
//模板名 => 模板路径
'default' => '@app/common/gii/model/default',
'original' => '@app/common/gii/model/original_tpl',
]
]
],
];

}

现在在配置中指定了两种model 生成模板了

2.设置自定义的 Geneartor 和 template

现在进@app/vendor/yiisoft/yii2-gii/src/generators/model把这个目录拷贝到 @app/common/gii/这里,位置随意, 只要保证 config 中能找到这个路径就行,现在我们就在 @app/common/gii/model这里操作

因为 Generator 继承的 \yii\gii\Generator, 需要实现两个方法, 一个是 getName() 另一个是 generate(), 我们主要修改的就是 generate(),

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
// file path: @app/common/gii/model/Generator
namespace app\common\gii\model;

use Yii;
use yii\db\ActiveQuery;
use yii\db\ActiveRecord;
use yii\db\Connection;
use yii\db\Schema;
use yii\db\TableSchema;
use yii\gii\CodeFile;
use yii\helpers\Inflector;
use yii\base\NotSupportedException;

class Generator extends \yii\gii\Generator{

/**
some code .....
*/
/**
* {@inheritdoc}
*/
public function generate()
{
$files = [];
$relations = $this->generateRelations();
$db = $this->getDbConnection();
foreach ($this->getTableNames() as $index => $tableName) {
// model :
$modelClassName = $this->generateClassName($tableName);
$queryClassName = ($this->generateQuery) ? $this->generateQueryClassName($modelClassName) : false;
$tableSchema = $db->getTableSchema($tableName);
$params = [
'tableName' => $tableName,
'className' => $modelClassName,
'queryClassName' => $queryClassName,
'tableSchema' => $tableSchema,
'properties' => $this->generateProperties($tableSchema),
'labels' => $this->generateLabels($tableSchema),
// 这是新增的
'constMap' => $this->generateConstMap($tableSchema),
'rules' => $this->generateRules($tableSchema),
'relations' => isset($relations[$tableName]) ? $relations[$tableName] : [],
];

// 同一个库中只生成一个 Model.php 之后的 model 都要继承这个 model
if ($index == 0) {
$files[] = new CodeFile(
Yii::getAlias('@' . str_replace('\\', '/', $this->ns)) . '/Model.php',
$this->render('cModel.php', $params)
);
}

$files[] = new CodeFile(
Yii::getAlias('@' . str_replace('\\', '/', $this->ns)) . '/' . $modelClassName . '.php',
$this->render('model.php', $params)
);


}

return $files;
}

protected function generateConstMap($table){
// some code
}



/**
some code .....
*/
}

generate() 这个方法里的 $params 这里就是给模板准备参数, new CodeFile这里就是生成指定的模板

现在我们在模板中搞一下

3.设置 model 模板

@app/common/gii/model目录下有一个default目录,就是默认的 template,咱们在config.php中设置了

1
2
3
4
5
'templates' => [
//模板名 => 模板路径
'default' => '@app/common/gii/model/default',
'original' => '@app/common/gii/model/original_tpl',
]

这两个, 把 default/ 复制一份叫 original_tpl/ 这在 gii 页面端选模板的时候能看到这写别名,如果是console模式的话只能使用default模板了

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
// path: @app/common/gii/default/model.php
<?php
/**
* This is the template for generating the model class of a specified table.
*/

/* @var $this yii\web\View */
/* @var $generator yii\gii\generators\model\Generator */
/* @var $tableName string full table name */
/* @var $className string class name */
/* @var $queryClassName string query class name */
/* @var $tableSchema yii\db\TableSchema */
/* @var $properties array list of properties (property => [type, name. comment]) */
/* @var $labels string[] list of attribute labels (name => label) */
/* @var $rules string[] list of validation rules */
/* @var $relations array list of relations (name => relation declaration) */
/* @var $constMap string[] list of attribute labels (name => label) */

echo "<?php\n";

?>

namespace <?= $generator->ns ?>;

use Yii;

/**
* This is the model class for table "<?= $generator->generateTableName($tableName) ?>".
*
<?php foreach ($properties as $property => $data): ?>

...底下一些乱七八糟的代码....

这里就看着办吧,就是正常的渲染模板

因为在generate()中还设置了一个

1
2
3
4
5
6
7
// 同一个库中只生成一个 Model.php 之后的 model 都要继承这个 model
if ($index == 0) {
$files[] = new CodeFile(
Yii::getAlias('@' . str_replace('\\', '/', $this->ns)) . '/Model.php',
$this->render('cModel.php', $params)
);
}

新增了一个cModel.php,这个是我自己的业务需求, 同库的 model 全部继承这个 model, 这里只是设置了一下getDb()方法

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
<?php
/**
* This is the template for generating the model class of a specified table.
*/

/* @var $this yii\web\View */
/* @var $generator yii\gii\generators\model\Generator */
/* @var $tableName string full table name */
/* @var $className string class name */
/* @var $queryClassName string query class name */
/* @var $tableSchema yii\db\TableSchema */
/* @var $properties array list of properties (property => [type, name. comment]) */
/* @var $labels string[] list of attribute labels (name => label) */
/* @var $rules string[] list of validation rules */
/* @var $relations array list of relations (name => relation declaration) */
/* @var $constMap string[] list of attribute labels (name => label) */

$date = date('Y/m/d H:i');
$date = explode(' ', $date);


$model = <<<str
<?php
/**
* Created by Gii.
* TemplatePath: @app\common\gii\model\default\cModel.php
* Date: {$date[0]}
* Time: {$date[1]}
*/
namespace {$generator->ns};
use yii\db\ActiveRecord;
use Yii;

/**
* 同文件夹下都要继承一下这个 model,目前是用来改库的链接地址
* Class Model
* @package app\modules\v1\models\passport
*/
class Model extends ActiveRecord
{

/**
* 重写表所对应的数据库链接信息 (如果函数不存在则默认为 db 的配置)
* @return \yii\db\Connection
*/
public static function getDb()
{
return Yii::\$app->get('{$generator->db}');
}
}
str;


echo $model;

?>

这样依赖 gii 的模板自定义就算是完事了

4. console 模式下的 gii

照例首先需要设置console.php的配置

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
//path @app/console.php
if (YII_ENV_DEV) {
// configuration adjustments for 'dev' environment
$config['bootstrap'][] = 'gii';
$config['modules']['gii'] = [
'class' => 'app\common\gii\Module',
'generators' => [
'model' => [
// 自定义的模板生成器
'class' => 'app\common\gii\model\Generator',
//设置我们自己的模板 console 默认就是 default 模板
'templates' => []
]
],
];
}

generators 和 之前的配置一样,区别就是 module 下的 class 设置成自己的 Module

这里把@app/vendor/yiisoft/yii2-gii/src/Module.php复制一份到@app/common/gii/Module.php 改一下命名空间并且继承\yii\gii\Module 毕竟咱们是定制的, 这个代码不能在 vendor 中改,不然以后你再装新的 composer 包的时候会非常麻烦

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
// path: @app/common/gii/Module.php

/**
代码块
*/
public function bootstrap($app)
{
if ($app instanceof \yii\web\Application) {
$app->getUrlManager()->addRules([
['class' => 'yii\web\UrlRule', 'pattern' => $this->id, 'route' => $this->id . '/default/index'],
['class' => 'yii\web\UrlRule', 'pattern' => $this->id . '/<id:\w+>', 'route' => $this->id . '/default/view'],
['class' => 'yii\web\UrlRule', 'pattern' => $this->id . '/<controller:[\w\-]+>/<action:[\w\-]+>', 'route' => $this->id . '/<controller>/<action>'],
], false);
} elseif ($app instanceof \yii\console\Application) {
$app->controllerMap[$this->id] = [
// 这里改成自己定制的 consoleController
'class' => 'app\common\gii\console\GenerateController',
'generators' => array_merge($this->coreGenerators(), $this->generators),
'module' => $this,
];
}
}
/**
代码块
*/

只用把 console 的 GenerateController 指向咱们自定义的控制器, 复制目录@app/vendor/yiisoft/yii2-gii/src/console/@app/common/gii/console/, 这时我们就能对 gii console 模式下的代码进行调整了

可能在@app/common/gii/console/GenerateController.php中的代码让你摸不到头脑, 这里是在 actions()来着注册 router, 具体的 action 实现则是在 class 中指定了

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
// path: @app/common/gii/console/GenerateController.php
public function actions()
{
$actions = [];
foreach ($this->generators as $name => $generator) {
$actions[$name] = [
'class' => 'yii\gii\console\GenerateAction',
'generator' => $generator,
];

// 依赖model generator 重新定义一个 gii 命令
if($name == 'model') {
$actions['all'] = [
'class' => 'app\common\gii\console\GenerateAllAction',
'generator' => $generator,
];
}
}
return $actions;
}

因为所有的 Generator 都实现了 getName()generate()这两个方法,action 也是只使用了这两个方法,可以自己翻下代码,这里就不详细讲了