开发是需要用到 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 也是只使用了这两个方法,可以自己翻下代码,这里就不详细讲了