Dcat Admin 自帶了 Model 模型生成器,但生成的類中並沒有表字段對應的 @property 屬性註解,這裏對源碼做了一些修改和完善,增加了對應字段的註解。
NOTICE: 僅限使用數據庫中已存在的表生成模型類的場景,如果是通過面板創建新表則不能(兼容起來太麻煩了)
需要修改或配置如下3文件
1. 模型類模版
src/Scaffold/stubs/model.stub
<?php
namespace DummyNamespace;
DummyImportDateTimeFormatterTrait
DummyImportSoftDeletesTrait
use Illuminate\Database\Eloquent\Model;
/**
* 創建時間 DummyCreatedAt
* @package DummyNamespace
*
DummyComments
*/
class DummyClass extends Model
{
DummyUseDateTimeFormatterTrait
DummyUseSoftDeletesTrait
DummyModelTable
DummyModelKey
DummyTimestamp
DummyCasts
}
2. 模型類生成器
\Dcat\Admin\Scaffold\ModelCreator:新增 replaceComment 方法,並在 create 方法中註冊。
/**
* The connection of database.
* @var string
*/
protected string $connection;
/**
* ModelCreator constructor.
*
* @param string $tableName
* @param string $name
* @param null $files
* @param string $connection
*/
public function __construct($tableName, $name, $files = null, string $connection = '')
{
$this->tableName = $tableName;
$this->name = $name;
$this->files = $files ?: app('files');
$this->connection = $connection ?: config('database.default');
}
/**
* Create a new migration file.
*
* @param string $keyName
* @param bool|true $timestamps
* @param bool|false $softDeletes
* @return string
*
* @throws \Exception
*/
public function create($keyName = 'id', $timestamps = true, $softDeletes = false)
{
...
$stub = $this->replaceClass($stub, $this->name)
->replaceNamespace($stub, $this->name)
->replaceSoftDeletes($stub, $softDeletes)
->replaceDatetimeFormatter($stub)
->replaceTable($stub, $this->name)
->replaceTimestamp($stub, $timestamps)
->replacePrimaryKey($stub, $keyName)
->replaceComments($stub, $timestamps, $softDeletes)
->replaceSpace($stub);
....
}
/**
* replace comment.
* @param $stub
* @param $userTimestamps
* @param $userSoftDeletes
*
* @return $this
*/
public function replaceComments(&$stub, $userTimestamps = true, $userSoftDeletes = false)
{
$table_name = config('database.connections.'.$this->connection.'.prefix').$this->tableName;
$db_name = config('database.connections.'.$this->connection.'.database');
$column_type_mappings = config('database.column_type_mappings');
$sql = "SELECT `column_name`,`column_comment`,`data_type` FROM `information_schema`.`columns` WHERE `table_name`='".$table_name."' AND `table_schema`='".$db_name."'";
$columns = DB::connection($this->connection)->select($sql);
$casts = [];
if ($columns) {
foreach ($columns as $key => $column) {
$type = $column_type_mappings[$column->data_type] ?? 'unknown';
$comments[] = " * @property $type $column->column_name $column->column_comment";
if ('datetime' == $type || '\Carbon\Carbon' == $type) {
$casts[$column->column_name] = 'datetime';
}
if ('array' == $type) {
$casts[$column->column_name] = 'json';
}
}
}
$comments = implode(PHP_EOL, $comments);
$stub = str_replace('DummyComments', $comments, $stub);
$stub = str_replace('DummyCreatedAt', Carbon::now()->toDateTimeString(), $stub);
$stub = str_replace('DummyCasts', 'protected $casts = '.var_export($casts, true) . ';', $stub);
return $this;
}
3. 模型屬性類型映射關係
config/database.php
<?php
return [
// 自定義數據列字段類型映射關係
'column_type_mappings' => [
'bit' => 'int',
'tinyint' => 'int',
'smallint' => 'int',
'mediumint' => 'int',
'int' => 'int',
'integer' => 'int',
'bigint' => 'int',
'decimal' => 'float',
'numeric' => 'float',
'float' => 'float',
'double' => 'float',
'date' => 'string',
'time' => 'string',
'datetime' => '\Carbon\Carbon',
'timestamp' => '\Carbon\Carbon',
'year' => 'string',
'char' => 'string',
'varchar' => 'string',
'tinytext' => 'string',
'text' => 'string',
'mediumtext' => 'string',
'longtext' => 'string',
'binary' => 'string',
'varbinary' => 'string',
'tinyblob' => 'string',
'blob' => 'string',
'mediumblob' => 'string',
'longblob' => 'string',
'enum' => 'array',
'set' => 'array',
'json' => 'array',
],
]
附加一個命令行工具類
<?php
namespace App\Console\Commands;
use Dcat\Admin\Scaffold\ModelCreator;
use Illuminate\Console\Command;
use Illuminate\Support\Facades\File;
use Illuminate\Support\Facades\Schema;
/**
* 生成模型 自動添加註解
* Class MakeModelCmd
* php artisan app:model-creator users User [-c mysql -t -s -r]
* @package App\Console\Commands
*/
class ModelCreatorCmd extends Command
{
/**
* The name and signature of the console command.
*
* @var string
*/
protected $signature = 'app:model-creator
{table : Name of the table in database: users}
{model : Name of the model: User or full namespace like App\\Models\\User}
{--c|connection= : connection name}
{--t|timestamps : turn on timestamps}
{--s|softDelete : turn on softDelete}
{--r|rewrite : turn on rewrite}';
/**
* The console command description.
*
* @var string
*/
protected $description = '創建模型類,可以指定數據庫連接、是否添加時間戳、軟刪除、是否覆蓋已存在文件';
/**
* Create a new command instance.
*
* @return void
*/
public function __construct()
{
parent::__construct();
}
/**
* Execute the console command.
*
* @return int
* @throws \Exception
*/
public function handle(): int
{
$table = $this->argument('table');
$model = $this->argument('model');
$connection = $this->option('connection') ?: config('database.default');
// 如果沒有指定命名空間,則默認加上App\Models
if (!str_contains($model, '\\')) {
$model = 'App\\Models\\'.ucfirst($model);
}
$mc = (new ModelCreator($table, $model, null, $connection));
$model_path = $mc->getPath($model);
// 如果文件存在且需要重寫,則刪除原文件
if (File::exists($model_path) && $this->option('rewrite')) {
File::delete($model_path);
}
$model_path = $mc->create('id',
$this->option('timestamps'),
$this->option('softDelete')
);
$this->info("Model created successfully: {$model_path}");
return self::SUCCESS;
}
}