创建脚本

优质
小牛编辑
130浏览
2023-12-01

Hyperf 提供了创建模型的命令,您可以很方便的根据数据表创建对应模型。命令通过 AST 生成模型,所以当您增加了某些方法后,也可以使用脚本方便的重置模型。

php bin/hyperf.php gen:model table_name

创建模型

可选参数如下:

参数类型默认值备注
--poolstringdefault连接池,脚本会根据当前连接池配置创建
--pathstringapp/Model模型路径
--force-castsboolfalse是否强制重置 casts 参数
--prefixstring空字符串表前缀
--inheritancestringModel父类
--usesstringHyperf\DbConnection\Model\Model配合 inheritance 使用
--refresh-fillableboolfalse是否刷新 fillable 参数
--table-mappingarray[]为表名 -> 模型增加映射关系 比如 ['users:Account']
--ignore-tablesarray[]不需要生成模型的表名 比如 ['users']
--with-commentsboolfalse是否增加字段注释
--property-caseint0字段类型 0 蛇形 1 驼峰

当使用 --property-case 将字段类型转化为驼峰时,还需要手动在模型中加入 Hyperf\Database\Model\Concerns\CamelCase

对应配置也可以配置到 databases.{pool}.commands.gen:model 中,如下

中划线都需要转化为下划线

<?php

declare(strict_types=1);

use Hyperf\Database\Commands\ModelOption;

return [
    'default' => [
        // 忽略其他配置
        'commands' => [
            'gen:model' => [
                'path' => 'app/Model',
                'force_casts' => true,
                'inheritance' => 'Model',
                'uses' => '',
                'refresh_fillable' => true,
                'table_mapping' => [],
                'with_comments' => true,
                'property_case' => ModelOption::PROPERTY_SNAKE_CASE,
            ],
        ],
    ],
];

创建的模型如下

<?php

declare(strict_types=1);

namespace App\Model;

use Hyperf\DbConnection\Model\Model;

/**
 * @property $id
 * @property $name
 * @property $gender
 * @property $created_at
 * @property $updated_at
 */
class User extends Model
{
    /**
     * The table associated with the model.
     *
     * @var string
     */
    protected $table = 'user';

    /**
     * The attributes that are mass assignable.
     *
     * @var array
     */
    protected $fillable = ['id', 'name', 'gender', 'created_at', 'updated_at'];

    /**
     * The attributes that should be cast to native types.
     *
     * @var array
     */
    protected $casts = ['id' => 'integer', 'gender' => 'integer'];
}

Visitors

框架提供了几个 Visitors,方便用户对脚本能力进行扩展。使用方法很简单,只需要在 visitors 配置中,添加对应的 Visitor 即可。

<?php

declare(strict_types=1);

return [
    'default' => [
        // 忽略其他配置
        'commands' => [
            'gen:model' => [
                'visitors' => [
                    Hyperf\Database\Commands\Ast\ModelRewriteKeyInfoVisitor::class
                ],
            ],
        ],
    ],
];

可选 Visitors

  • Hyperf\Database\Commands\Ast\ModelRewriteKeyInfoVisitor

Visitor 可以根据数据库中主键,生成对应的 $incrementing $primaryKey$keyType

  • Hyperf\Database\Commands\Ast\ModelRewriteSoftDeletesVisitor

Visitor 可以根据 DELETED_AT 常量判断该模型是否含有软删除字段,如果存在,则添加对应的 Trait SoftDeletes

  • Hyperf\Database\Commands\Ast\ModelRewriteTimestampsVisitor

Visitor 可以根据 created_atupdated_at 自动判断,是否启用默认记录 创建和修改时间 的功能。

  • Hyperf\Database\Commands\Ast\ModelRewriteGetterSetterVisitor

Visitor 可以根据数据库字段生成对应的 gettersetter

覆盖 Visitor

Hyperf 框架中,当使用 gen:model 时,默认会将 decimal 转化成为 float。如下:

<?php

declare(strict_types=1);

namespace App\Model;

/**
 * @property int $id
 * @property int $count
 * @property float $float_num // decimal
 * @property string $str
 * @property string $json
 * @property \Carbon\Carbon $created_at
 * @property \Carbon\Carbon $updated_at
 */
class UserExt extends Model
{
    /**
     * The table associated with the model.
     *
     * @var string
     */
    protected $table = 'user_ext';

    /**
     * The attributes that are mass assignable.
     *
     * @var array
     */
    protected $fillable = ['id', 'count', 'float_num', 'str', 'json', 'created_at', 'updated_at'];

    /**
     * The attributes that should be cast to native types.
     *
     * @var array
     */
    protected $casts = ['id' => 'integer', 'count' => 'integer', 'float_num' => 'float', 'created_at' => 'datetime', 'updated_at' => 'datetime'];
}

这时候,我们就可以通过重写 ModelUpdateVisitor,修改这一特性。

<?php

declare(strict_types=1);
/**
 * This file is part of Hyperf.
 *
 * @link     https://www.hyperf.io
 * @document https://hyperf.wiki
 * @contact  group@hyperf.io
 * @license  https://github.com/hyperf/hyperf/blob/master/LICENSE
 */
namespace App\Kernel\Visitor;

use Hyperf\Database\Commands\Ast\ModelUpdateVisitor as Visitor;
use Hyperf\Utils\Str;

class ModelUpdateVisitor extends Visitor
{
    protected function formatDatabaseType(string $type): ?string
    {
        switch ($type) {
            case 'tinyint':
            case 'smallint':
            case 'mediumint':
            case 'int':
            case 'bigint':
                return 'integer';
            case 'decimal':
                // 设置为 decimal,并设置对应精度
                return 'decimal:2';
            case 'float':
            case 'double':
            case 'real':
                return 'float';
            case 'bool':
            case 'boolean':
                return 'boolean';
            default:
                return null;
        }
    }

    protected function formatPropertyType(string $type, ?string $cast): ?string
    {
        if (! isset($cast)) {
            $cast = $this->formatDatabaseType($type) ?? 'string';
        }

        switch ($cast) {
            case 'integer':
                return 'int';
            case 'date':
            case 'datetime':
                return '\Carbon\Carbon';
            case 'json':
                return 'array';
        }

        if (Str::startsWith($cast, 'decimal')) {
            // 如果 cast 为 decimal,则 @property 改为 string
            return 'string';
        }

        return $cast;
    }
}

配置映射关系 dependencies.php

<?php

return [
    Hyperf\Database\Commands\Ast\ModelUpdateVisitor::class => App\Kernel\Visitor\ModelUpdateVisitor::class,
];

重新执行 gen:model 后,对应模型如下:

<?php

declare (strict_types=1);

namespace App\Model;

/**
 * @property int $id 
 * @property int $count 
 * @property string $float_num 
 * @property string $str 
 * @property string $json 
 * @property \Carbon\Carbon $created_at 
 * @property \Carbon\Carbon $updated_at 
 */
class UserExt extends Model
{
    /**
     * The table associated with the model.
     *
     * @var string
     */
    protected $table = 'user_ext';
    /**
     * The attributes that are mass assignable.
     *
     * @var array
     */
    protected $fillable = ['id', 'count', 'float_num', 'str', 'json', 'created_at', 'updated_at'];
    /**
     * The attributes that should be cast to native types.
     *
     * @var array
     */
    protected $casts = ['id' => 'integer', 'count' => 'integer', 'float_num' => 'decimal:2', 'created_at' => 'datetime', 'updated_at' => 'datetime'];
}