laravel根据现有数据库的表生成模型文件(artisan指令版本)

laravel根据现有数据库的表生成模型文件(artisan指令版本)

laravel版本 7.2.2

使用示例(–参数可以灵活组合):

  1. 生成数据库中所有表的模型文件
     php artisan generate:model
  2. 生成数据库中所有表的模型文件到指定文件夹下
     php artisan generate:model --path=app/Models/Cs
  3. 生成数据库中所有表的模型文件 模型类名和模型文件名通过表名字段的_进行大驼峰的命名组合
     php artisan generate:model --table_combo_str=_
  4. 生成数据库中指定表的模型文件
     php artisan generate:model --table="user,admin"
  5. 生成数据库中指定模糊匹配的表名的模型文件,要配合–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 协议》,转载必须注明作者和本文链接
《L01 基础入门》
我们将带你从零开发一个项目并部署到线上,本课程教授 Web 开发中专业、实用的技能,如 Git 工作流、Laravel Mix 前端工作流等。
《L04 微信小程序从零到发布》
从小程序个人账户申请开始,带你一步步进行开发一个微信小程序,直到提交微信控制台上线发布。
讨论数量: 2

讨论应以学习和精进为目的。请勿发布不友善或者负能量的内容,与人为善,比聪明更重要!