laravel根据现有数据库的表生成模型文件(artisan指令版本)
laravel根据现有数据库的表生成模型文件(artisan指令版本)
laravel版本 7.2.2
使用示例(–参数可以灵活组合):
- 生成数据库中所有表的模型文件
php artisan generate:model
- 生成数据库中所有表的模型文件到指定文件夹下
php artisan generate:model --path=app/Models/Cs
- 生成数据库中所有表的模型文件 模型类名和模型文件名通过表名字段的
_
进行大驼峰的命名组合php artisan generate:model --table_combo_str=_
- 生成数据库中指定表的模型文件
php artisan generate:model --table="user,admin"
- 生成数据库中指定模糊匹配的表名的模型文件,要配合–table使用,多个table的话会对每个table都会模糊匹配,是OR的关系(fuzzy_match 1为不开启 2为前匹配 3为后匹配 4为中间匹配)
php artisan generate:model --table="user,admin" --fuzzy_match=2
代码
<?php
namespace App\Console\Commands;
use Illuminate\Console\Command;
use Illuminate\Support\Facades\DB;
/**
* 根据数据库现有的表生成模型
* Class GenerateModel
* @package App\Console\Commands
*/
class GenerateModel extends Command
{
/**
* 命令行执行命令
* @var string
*/
protected $signature = 'generate:model {--table=} {--path=} {--table_combo_str=} {--fuzzy_match=}';
/**
* 命令描述
*
* @var string
*/
protected $description = '生成模型文件 [--table=可选参数为指定的数据表 可以有多个 `,`隔开,不传的话为所有表] [--fuzzy_match=是否开启表名的模糊匹配,1为不开启 2为前匹配 3为后匹配 4为中间匹配 默认为1] [--path=可选参数指定模型文件存放的路径,想对于项目根目录的路径,默认路径为 app/Models] [--table_combo_str=表单词分离的字符默认为 `_` ]';
/*表名的模糊匹配模式*/
const FUZZY_MATCH_NOT_OPEN = 1; //不开启
const FUZZY_MATCH_PREFIX = 2; //前缀匹配
const FUZZY_MATCH_SUFFIX = 3; //前缀匹配
const FUZZY_MATCH_MIDDLE = 4; //中间匹配
/**
* Execute the console command.
*
* @return mixed
*/
public function handle()
{
//自定义文件存放地址
$path = $this->option("path");
//需要生成的表的模型(默认为全部)
$table = $this->option("table");
$table = !empty($table) ? explode(",",$table) :[];
$this->generate($path,env("DB_DATABASE"),$table);
}
/**
* 执行生成模型文件
* @param $database_name
* @param $table
*/
public function generate($path,$database_name,$table)
{
//获取表的信息
$tables= $this->getTableInfo($database_name,$table);
foreach ($tables as $v) {
$this->generateModel($path,$v);
}
}
/**
* 获取表的字段信息
* @param $table_name
* @return array
*/
public function getFields($table_name)
{
return DB::select("show FULL COLUMNS from {$table_name}");
}
/**
* 获取表信息
* @param $database_name -数据库名
* @param $table -查询的表名 默认为全查询
*/
public function getTableInfo($database_name,$table)
{
//表名的匹配模式
$fuzzy_match = $this->option("fuzzy_match") ?? self::FUZZY_MATCH_NOT_OPEN;
if($fuzzy_match != self::FUZZY_MATCH_NOT_OPEN && empty($table)) {
echo "开启表名模糊匹配 `--fuzzy_match=` 后,请传递具体的表名参数 `--table=` ";
exit();
}
$sql = "SELECT TABLE_NAME as table_name,TABLE_COMMENT as comment FROM information_schema.TABLES WHERE table_schema='{$database_name}'";
if(!empty($table) && is_array($table)) {
$rule = "IN";
$where = "";
switch ($fuzzy_match) {
//不模糊匹配
case self::FUZZY_MATCH_NOT_OPEN:
foreach ($table as $t) {
if (empty($where)) {
$where .= "('" . $t . "'";
} else {
$where .= ",'" . $t . "'";
}
}
$where .= ")";
break;
//前缀匹配
case self::FUZZY_MATCH_PREFIX:
$rule = "like";
foreach ($table as $t) {
if(empty($where)) {
$where .= "'%".$t."'";
}else{
$where .= " OR table_name like '%".$t."'";
}
}
break;
//后缀匹配
case self::FUZZY_MATCH_SUFFIX:
$rule = "like";
foreach ($table as $t) {
if(empty($where)) {
$where .= "'".$t."%'";
}else{
$where .= " OR table_name like '".$t."%'";
}
}
break;
//中间匹配
case self::FUZZY_MATCH_MIDDLE:
$rule = "like";
foreach ($table as $t) {
if(empty($where)) {
$where .= "'%".$t."%'";
}else{
$where .= " OR table_name like '%".$t."%'";
}
}
break;
default:
echo "--fuzzy_match= 传递了非法的参数,只允许传递【 1为不开启 2为前匹配 3为后匹配 4为中间匹配 】";
exit();
}
$sql .= " AND (table_name {$rule} {$where})";
}
return DB::select($sql);
}
/**
* 执行生成模型文件
* @param $table_name
* @param $fields
*/
public function generateModel($path,$table_info)
{
//表名
$table_name = $table_info["table_name"];
//表名的单词连接方式,用于分解单词并使用大驼峰连接成模型名&文件名
$table_combo_str = $this->option("table_combo_str") ?? "_";
$table_name_array = explode($table_combo_str,$table_name);
//模型名称,采用大驼峰命名法
$model_class_name = "";
foreach ($table_name_array as $v) {
$model_class_name .= ucfirst($v);
}
//获取表的字段信息,包含表名和注释
$fields = $this->getFields($table_name);
$field_string = "";
$comment_sting = <<< EOF
/**
* Class {$model_class_name} {$table_info["comment"]}\n
EOF;
$field_num = 0;
foreach ($fields as $field) {
$field_num++;
if(empty($field_string)){
$field_string = "'".$field["Field"]."'";
}else{
//防止单行过长,超过六个字段名就换行
if($field_num > 6){
$field_num = 0;
$field_string .=",\n '".$field["Field"]."'";
}else{
$field_string .= ",'".$field["Field"]."'";
}
}
//添加字段注释
if(!empty($field["Comment"])){
$comment_sting .= "* @property {$field["Field"]} #{$field["Comment"]} \n";
}else{
$comment_sting .= "* @property {$field["Field"]}\n";
}
}
$comment_sting .= "*/";
//模型文件名名称
$model_file_name = $model_class_name.".php";
$namespace_name = "App\Models";
if(!empty($path)) {
$namespace_name = ucwords(str_replace("/","\\",$path),"\\");
}
//模型文件内容
$content = <<< EOF
<?php
namespace {$namespace_name};\n\n
use Illuminate\Database\Eloquent\Model;\n\n
{$comment_sting}
class {$model_class_name} extends Model {
/**
* 与模型关联的表名
* @var string
*/
protected \$table = '{$table_name}';
/**
* 指示模型是否自动维护时间戳
* @var bool
*/
public \$timestamps = false;
/**
* 模型日期列的存储格式。
* @var string
*/
protected \$dateFormat = 'Y-m-d H:i:s';
protected \$fillable= [\n {$field_string}\n ];
}
EOF;
//模型文件存放路径
$folder = base_path($path);
//文件路径的采用小驼峰命名法
$folder = lcfirst($folder);
$file_path = $folder."/".$model_file_name;
if(file_exists($file_path)){
echo "{$table_name} 表的模型文件已经存在,模型文件路径为:{$file_path}\n";
}else{
if(!is_dir($folder)){
mkdir($folder, 0700,true);
}
$file = fopen($file_path, "w");
$res = fwrite($file,$content);
if(!$res) {
echo "{$table_name} 表的模型文件生成失败,请重试\n";
}
fclose($file);
}
}
}
本作品采用《CC 协议》,转载必须注明作者和本文链接
github.com/reliese/laravel