hyperf/docs/zh-hk/db/gen.md
2021-04-06 09:05:21 +08:00

8.5 KiB
Raw Blame History

模型創建腳本

Hyperf 提供了創建模型的命令,您可以很方便的根據數據表創建對應模型。命令通過 AST 生成模型,所以當您增加了某些方法後,也可以使用腳本方便的重置模型。

php bin/hyperf.php gen:model table_name

創建模型

可選參數如下:

參數 類型 默認值 備註
--pool string default 連接池,腳本會根據當前連接池配置創建
--path string app/Model 模型路徑
--force-casts bool false 是否強制重置 casts 參數
--prefix string 空字符串 表前綴
--inheritance string Model 父類
--uses string Hyperf\DbConnection\Model\Model 配合 inheritance 使用
--refresh-fillable bool false 是否刷新 fillable 參數
--table-mapping array [] 為表名 -> 模型增加映射關係 比如 ['users:Account']
--ignore-tables array [] 不需要生成模型的表名 比如 ['users']
--with-comments bool false 是否增加字段註釋
--property-case int 0 字段類型 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'];
}