yii可以通过 数据表 自动生成model,为了laravel实现其同样功能,写了如下脚本。
还可以自动生成service controller,并且model通过数据表类型做了自动验证规则。
1.新建app/Console/Commands/MakeMCS.php文件。
以下代码复制进去
<?php
namespace App\Console\Commands;
use Illuminate\Console\Command;
use Illuminate\Support\Facades\DB;
class MakeMCS extends Command
{
/**
* The name and signature of the console command.
*
* @var string
*/
protected $signature = 'make:mcs {table} {--t=m} {--d=}';
/**
* The console command description.
*
* @var string
*/
protected $description = 'make model controller service';
protected $makeType = [
'm' => 'makeModel',
'c' => 'makeController',
's' => 'makeService',
];
/**
* Create a new command instance.
*
* @return void
*/
public function __construct()
{
parent::__construct();
}
/**
* Execute the console command.
*
* @return mixed
*/
public function handle()
{
if (env('APP_ENV', 'production') != 'local') {
echo "err \n";exit();
}
$tableName = $this->argument('table');
$type = $this->option('t');
$dir = $this->option('d');
if (!isset($this->makeType[$type])) {
echo '生成文件类型不存在' . PHP_EOL;
exit();
}
$dbName = config('database');
$columns = DB::select("
SELECT COLUMN_NAME, DATA_TYPE , COLUMN_COMMENT,ORDINAL_POSITION,CHARACTER_MAXIMUM_LENGTH
FROM INFORMATION_SCHEMA.COLUMNS
WHERE table_name = '{$dbName['connections']['mysql']['prefix']}{$tableName}'
AND table_schema = '{$dbName['connections']['mysql']['database']}' ORDER BY ORDINAL_POSITION");
call_user_func_array([$this, $this->makeType[$type]], [$tableName, $dir, $columns]);
echo "success \n";
exit();
}
/**
* Notes:生成model
* Date: 2022/11/21
* @param $tableName
* @param $dir
* @param $columns
*/
public function makeModel($tableName, $dir, $columns)
{
$property = "";
$fillable = "";
$rules = "";
$attributeLabels = "";
$toDetailsArr = "";
//dd($columns);
foreach ($columns as $column) {
$type = 'string';
$ruleType = 'string';
if (in_array($column->DATA_TYPE, ['int', 'tinyint', 'smallint', 'mediumint', 'bigint'])) {
$type = 'int';
$ruleType = 'integer';
} elseif (in_array($column->DATA_TYPE, ['float', 'double', 'decimal'])) {
$type = 'float';
$ruleType = 'numeric';
}
$columnName = $column->COLUMN_NAME;
$columnComment = $column->COLUMN_COMMENT;
$property .= sprintf(" * @property %s \$%s %s\n", $type, $columnName, $columnComment);
$fillable .= "'{$columnName}',";
//if($columnName=='id')$columnName=$tableName.'_id';
$attributeLabels .= "\t\t\t'{$columnName}' => '{$column->COLUMN_COMMENT}',\n";
if (!in_array($columnName, ['id', 'updated_at', 'created_at', 'is_del'])) {
$rules .= "\t\t\t'{$columnName}' => '{$ruleType}";
$ruleLength = "',\n";
if (!empty($column->CHARACTER_MAXIMUM_LENGTH)) {
$ruleLength = "|max:{$column->CHARACTER_MAXIMUM_LENGTH}',\n";
}
$rules .= $ruleLength;
}
$format = $tableColumnName = '';
if (in_array($columnName, ['updated_at', 'created_at'])) {
$format = "->format('Y-m-d H:i')";
}
if ($columnName == 'id') $tableColumnName = $tableName . '_';
$toDetailsArr .= "\t\t\t'{$tableColumnName}{$columnName}' => \$this->{$columnName}{$format},\n";
}
$property = trim($property, PHP_EOL . " ");
$fillable = trim($fillable, ",");
$rules = trim($rules, PHP_EOL . "\t");
$attributeLabels = trim($attributeLabels, PHP_EOL . "\t");
$toDetailsArr = trim($toDetailsArr, PHP_EOL . "\t");
//dd($rules);
$stub = file_get_contents(resource_path("stubs/Model.stub"));
$namespace = $dir ? '\\' . $this->camelize($dir) : '';
$modelName = $this->camelize($tableName);
$modelTemplate = str_replace(
[
'{{namespace}}',
'{{modelName}}',
'{{tableName}}',
'{{propertyContent}}',
'{{fillable}}',
'{{rules}}',
'{{attributeLabels}}',
'{{toDetailsArr}}',
],
[
$namespace,
$modelName,
$tableName,
$property,
$fillable,
$rules,
$attributeLabels,
$toDetailsArr,
],
$stub
);
$dir = $dir ? '/' . $this->camelize($dir) : '';
$dir = app_path("Models/Admin{$dir}");
if (!is_dir($dir)) mkdir($dir);
$file = "{$dir}/{$modelName}.php";
$this->fileExists($file);
file_put_contents($file, $modelTemplate);
return true;
//file_put_contents("{$dir}/{$modelName}.php", $modelTemplate);
//file_put_contents(app_path("Model/{$mp}.php"), $modelTemplate);
}
/**
* Notes:生成controller
* Date: 2022/11/21
* @param $tableName
* @param $dir
* @param $columns
*/
public function makeController($tableName, $dir, $columns)
{
$getField = "";
foreach ($columns as $column) {
$columnName = $column->COLUMN_NAME;
if ($columnName == 'id') $columnName = $tableName . '_id';
if (!in_array($columnName, ['updated_at', 'created_at', 'is_del'])) {
$getField .= "'{$columnName}',";
}
}
$getField = trim($getField, ",");
$getId = $tableName . '_id';
$getCamelId = $this->camelize($getId, false);
//dd($rules);
$stub = file_get_contents(resource_path("stubs/Controller.stub"));
$namespace = $dir ? '\\' . $this->camelize($dir) : '';
$name = $this->camelize($tableName);
$controllerName = $serviceName = $modelName = $name;
$useService = "{$namespace}\\{$name}";
$useModel = "\\{$name}";
$modelTemplate = str_replace(
[
'{{namespace}}',
'{{controllerName}}',
'{{serviceName}}',
'{{useService}}',
'{{useModel}}',
'{{modelName}}',
'{{getField}}',
'{{getId}}',
'{{getCamelId}}',
],
[
$namespace,
$controllerName,
$serviceName,
$useService,
$useModel,
$modelName,
$getField,
$getId,
$getCamelId,
],
$stub
);
$dir = $dir ? '/' . $this->camelize($dir) : '';
$dir = app_path("Http/Controllers/Admin/Web{$dir}");
if (!is_dir($dir)) mkdir($dir);
$file = "{$dir}/{$controllerName}Controller.php";
$this->fileExists($file);
file_put_contents($file, $modelTemplate);
return true;
}
/**
* Notes:生成service
* Date: 2022/11/21
* @param $tableName
* @param $dir
* @param $columns
*/
public function makeService($tableName, $dir, $columns)
{
$returnField = "";
foreach ($columns as $column) {
$columnName = $column->COLUMN_NAME;
if ($columnName == 'id') $columnName = 'id as ' . $tableName . '_id';
if (!in_array($columnName, ['is_del'])) {
$returnField .= "'{$columnName}',";
}
}
$returnField = trim($returnField, ",");
$getId = $tableName . '_id';
$getCamelId = $this->camelize($getId, false);
//dd($rules);
$stub = file_get_contents(resource_path("stubs/Service.stub"));
$namespace = $dir ? '\\' . $this->camelize($dir) : '';
$name = $this->camelize($tableName);
$serviceName = $modelName = $name;
$useModel = "\\{$name}";
$modelTemplate = str_replace(
[
'{{namespace}}',
'{{serviceName}}',
'{{useModel}}',
'{{modelName}}',
'{{returnField}}',
'{{getId}}',
'{{getCamelId}}',
],
[
$namespace,
$serviceName,
$useModel,
$modelName,
$returnField,
$getId,
$getCamelId,
],
$stub
);
$dir = $dir ? '/' . $this->camelize($dir) : '';
$dir = app_path("Services/Admin{$dir}");
if (!is_dir($dir)) mkdir($dir);
$file = "{$dir}/{$serviceName}Service.php";
$this->fileExists($file);
file_put_contents($file, $modelTemplate);
return true;
}
/**
* Notes:验证文件是否存在
* Date: 2022/11/21
* @param $file
*/
public function fileExists($file)
{
if (file_exists($file)) {
fwrite(STDOUT, "该文件已存在,覆盖请输入 y;");
$sign = trim(fgets(STDIN), PHP_EOL);
if ($sign != 'y') {
echo sprintf("输入的 %s,已退出\n", $sign);
exit();
}
}
}
/***
* 下划线转驼峰
* @param string $str 字符串
* @param bool $firstToUpper 首字母是否大写
* @return mixed|string
*/
function camelize($str, $firstToUpper = true)
{
while (($pos = strpos($str, '_')) !== false)
$str = substr($str, 0, $pos) . ucfirst(substr($str, $pos + 1));
if ($firstToUpper)
return ucfirst($str);
else
return $str;
}
}
还需三个(model.stub service.stub controller.stub)配套模板,可以仔细阅读代码自己创建,也可私信我获取。
2.使用命令(控制台)
php artisan make:mcs 表名(生成文件名) --t=生成类型(m:模型 c:控制器 s:service) --d=目录(会自动转大写)
php artisan make:mcs test --t=m #创建model到,models目录下
php artisan make:mcs test --t=c --d=user #创建控制器到,controllers目录下的user目录
php artisan make:mcs test --t=s #创建service到,services目录下
3.生成样例
如果已有文件,会提示是否覆盖。
以下是按照个人习惯生成的文件,可以自己调整模板(上述自己需创建)按自己需求生成。
php .\artisan make:mcs user_test
<?php
namespace App\Models;
use App\Common\Api\Codes;
use Illuminate\Database\Eloquent\Model;
/**
* This is the model class for table "user_test".
*
* @property int $id
* @property string $name 姓名
* @property string $phone 手机号
* @property int $status 是否禁用 0=否 1=是
* @property string $created_at
* @property string $updated_at
*/
class UserTest extends Model
{
protected $table = 'user_test';
protected $fillable = ['id', 'name', 'phone', 'status', 'created_at', 'updated_at'];
protected $hidden = [];
/**
* {@inheritdoc}
*/
public static function rules()
{
return [
'name' => 'string|max:32',
'phone' => 'string|max:11',
'status' => 'integer',
];
}
/**
* {@inheritdoc}
*/
public static function rulesMsg()
{
return [
'string' => ':attribute 为字符型',
'max' => ':attribute 长度超出范围',
'integer' => ':attribute 必须是一个整型',
'numeric' => ':attribute 必须是一个数字',
];
}
/**
* {@inheritdoc}
*/
public static function attributeLabels()
{
return [
'id' => '',
'name' => '姓名',
'phone' => '手机号',
'status' => '是否禁用 0=否 1=是',
'created_at' => '',
'updated_at' => '',
];
}
/**
* {@inheritdoc}
*/
public static function validator(array $arr)
{
$validator = \Validator::make($arr, static::rules(), static::rulesMsg(), static::attributeLabels());
if ($validator->fails()) {
resp(Codes::PHONE_NUM_ERR)->msg($validator->errors()->first())->resp(true);
}
}
public function toDetailsArr(): array
{
return [
'user_test_id' => $this->id,
'name' => $this->name,
'phone' => $this->phone,
'status' => $this->status,
'created_at' => $this->created_at->format('Y-m-d H:i'),
'updated_at' => $this->updated_at->format('Y-m-d H:i'),
];
}
}