Laravel automatically generates model service controller scripts through commands (model with annotations)

Yii can automatically generate models through data tables. In order for laravel to achieve the same function, the following script was written.

Service controllers can also be automatically generated, and the model has automatic validation rules based on data table types.

1. Create a new app/Console/Commands/MakeMCS.php file.

Copy the following code into

<?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 \
";exit();
        }
        $tableName = $this->argument('table');
        $type = $this->option('t');
        $dir = $this->option('d');
        if (!isset($this->makeType[$type])) {
            echo 'The generated file type does not exist'. 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 \
";
        exit();
    }

    /**
     * Notes: Generate 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\
", $type, $columnName, $columnComment);
            $fillable .= "'{$columnName}',";
            //if($columnName=='id')$columnName=$tableName.'_id';
            $attributeLabels .= "\t\t\t'{$columnName}' => '{$column->COLUMN_COMMENT}',\
";
            if (!in_array($columnName, ['id', 'updated_at', 'created_at', 'is_del'])) {
                $rules .= "\t\t\t'{$columnName}' => '{$ruleType}";
                $ruleLength = "',\
";
                if (!empty($column->CHARACTER_MAXIMUM_LENGTH)) {
                    $ruleLength = "|max:{$column->CHARACTER_MAXIMUM_LENGTH}',\
";
                }
                $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},\
";
        }
        $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: Generate 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: Generate 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: Verify that the file exists
     * Date: 2022/11/21
     * @param $file
     */
    public function fileExists($file)
    {
        if (file_exists($file)) {
            fwrite(STDOUT, "The file already exists, please enter y to overwrite;");
            $sign = trim(fgets(STDIN), PHP_EOL);
            if ($sign != 'y') {
                echo sprintf("Input %s, exited\
", $sign);
                exit();
            }
        }
    }

    /***
     * Underscore to camel case
     * @param string $str string
     * @param bool $firstToUpper whether the first letter is capitalized
     * @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;
    }
}

Three more supporting templates are needed (model.stub service.stub controller.stub). You can read the code carefully to create it yourself, or you can send me a private message to get it.

2.Use command (console)

php artisan make:mcs table name (generated file name) --t=generation type (m:model c:controller s:service) --d=directory (will be automatically converted to uppercase)
php artisan make:mcs test --t=m #Create model in the models directory
php artisan make:mcs test --t=c --d=user #Create the controller to the user directory under the controllers directory
php artisan make:mcs test --t=s #Create service in the services directory

3. Generate samples

If the file already exists, you will be prompted whether to overwrite it.

The following are files generated according to personal habits. You can adjust the template yourself (the above needs to be created by yourself) and generate it according to your own needs.

 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 name
 * @property string $phone mobile phone number
 * @property int $status Whether to disable 0=no 1=yes
 * @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 is character type',
            'max' => ':attribute length exceeds range',
            'integer' => ':attribute must be an integer',
            'numeric' => ':attribute must be a number',
        ];
    }

    /**
     * {@inheritdoc}
     */
    public static function attributeLabels()
    {
        return [
            'id' => '',
            'name' => 'name',
            'phone' => 'Mobile phone number',
            'status' => 'Whether it is disabled 0=no 1=yes',
            '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'),
        ];
    }
}