Victoryoalli / laravel-code-generator
用于代码生成的PHP包。
4.0.0
2023-03-14 16:57 UTC
Requires
- php: ^8.0
- doctrine/dbal: ^2.9|^3.0
- illuminate/console: ^8.0|^9.0|^10.0
- illuminate/filesystem: ^8.0|^9.0|^10.0
- illuminate/support: ^8.0|^9.0|^10.0
- spatie/laravel-ray: ^1.18
Requires (Dev)
- orchestra/testbench: ^7.0|^8.0
- victoryoalli/laravel-string-macros: ^1.0
README
Laravel Code Generator 是一个PHP Laravel包,使用Blade模板引擎为您生成代码。
与其他代码生成器的不同之处在于,它将生成与您期望完全一致的代码,相同的设计,相同的代码行。
演示
安装
使用Composer安装Laravel Code Generator。
composer require --dev victoryoalli/laravel-code-generator
用法
单文件生成
php artisan code:generate 'App\Models\User' -t 'schema' //prints to command line php artisan code:generate 'App\Models\User' -t 'schema' -o 'user-schema.json'
示例输出
{ "name": "User", "complete_name": "App\\Models\\User", "table": { "name": "users", "columns": [ { "name": "id", "type": "BigInt", "length": "", "nullable": "", "autoincrement": "1", "default": "" }, { "name": "name", "type": "String", "length": "255", "nullable": "", "autoincrement": "", "default": "" }, { "name": "email", "type": "String", "length": "255", "nullable": "", "autoincrement": "", "default": "" }, { "name": "email_verified_at", "type": "DateTime", "length": "0", "nullable": "1", "autoincrement": "", "default": "" }, { "name": "password", "type": "String", "length": "255", "nullable": "", "autoincrement": "", "default": "" }, { "name": "remember_token", "type": "String", "length": "100", "nullable": "1", "autoincrement": "", "default": "" }, { "name": "created_at", "type": "DateTime", "length": "0", "nullable": "1", "autoincrement": "", "default": "" }, { "name": "updated_at", "type": "DateTime", "length": "0", "nullable": "1", "autoincrement": "", "default": "" } ] }, "relations": [] }
多文件生成器
首先创建一个自定义命令,例如以下示例
创建自定义命令
php artisan make:command CodeGeneratorCommand --command='code:generator'
自定义命令
<?php namespace App\Console\Commands; use Illuminate\Console\Command; use VictorYoalli\LaravelCodeGenerator\Facades\CodeGenerator; use VictorYoalli\LaravelCodeGenerator\Facades\ModelLoader; use VictorYoalli\LaravelCodeGenerator\Structure\Model; class CodeGeneratorCommand extends Command { /** * The name and signature of the console command. * * @var string */ protected $signature = 'code:generator {model : Model(s) separated by commas: i.e: \'User, Post, Section\' } ' . '{--namespace=App\Models : Models Namesspace} ' . '{--w|views : View files} ' . '{--c|controller : Controller} ' . '{--a|api : Creates API Controller} ' . '{--r|routes : Display Routes} ' . '{--l|lang : Language} ' . '{--A|all : All Files}' . '{--f|factory : Factory} ' . '{--t|tests : Feature Test} ' . '{--auth : Auth (not included in all)} ' . '{--event= : Event (not included in all)} ' . '{--notification= : Notification (not included in all)} ' . '{--F|force : Overwrite files if exists} ' . '{--livewire : Add livewire files}' . '{--theme=blade : Theme}'; protected $description = 'Multiple files generation'; /** * Execute the console command. * * @return mixed */ public function handle() { $force = $this->option('force'); //Options $controller = $this->option('controller'); $routes = $this->option('routes'); $views = $this->option('views'); $api = $this->option('api'); $lang = $this->option('lang'); $factory = $this->option('factory'); $tests = $this->option('tests'); $auth = $this->option('auth'); $event = $this->option('event'); $notification = $this->option('notification'); $all = $this->option('all'); $livewire = $this->option('livewire'); $theme = $this->option('theme'); if ($all) { $lang = $controller = $routes = $views = $all; } $request = ($controller || $api); $options = compact(['factory', 'controller', 'routes', 'views', 'api', 'tests', 'auth', 'request', 'notification', 'event', 'lang','livewire']); $namespace = rtrim($this->option('namespace'), '\\'); $models = collect(explode(',', $this->argument('model'))); $models->each(function ($model) use ($namespace, $options, $theme, $force) { $model = "{$namespace}\\{$model}"; if (!$model) { return; } $m = ModelLoader::load($model); $this->generate($m, $options, $theme, $force); }); } public function generate(Model $m, $options, $theme, $force) { $option = (object) $options; $folder = str($m->name)->plural()->snake(); $this->info('🚀 Starting code generation'); $this->newLine(); if ($option->controller) { $this->printif('Web Controller', CodeGenerator::generate($m, $theme . '/Http/Controllers/ModelController', "app/Http/Controllers/{$m->name}Controller.php", $force, $options)); } if ($option->api) { $this->printif('API Controller', CodeGenerator::generate($m, $theme . '/Http/Controllers/API/ModelController', "app/Http/Controllers/API/{$m->name}Controller.php", $force, $options)); } if ($option->request) { $this->printif('Form Request', CodeGenerator::generate($m, $theme . '/Http/Requests/ModelRequest', "app/Http/Requests/{$m->name}Request.php", $force, $options)); } if ($option->views) { $this->printif('Index View', CodeGenerator::generate($m, $theme . '/views/index', "resources/views/{$folder}/index.blade.php", $force, $options)); $this->printif('Create View', CodeGenerator::generate($m, $theme . '/views/create', "resources/views/{$folder}/create.blade.php", $force, $options)); $this->printif('Show View', CodeGenerator::generate($m, $theme . '/views/show', "resources/views/{$folder}/show.blade.php", $force, $options)); $this->printif('Edit View', CodeGenerator::generate($m, $theme . '/views/edit', "resources/views/{$folder}/edit.blade.php", $force, $options)); } if ($option->lang) { $this->printif('Lang', CodeGenerator::generate($m, $theme . '/lang/en/Models', "resources/lang/en/{$folder}.php", $force, $options)); } if ($option->factory) { $this->printif('Factory ', CodeGenerator::generate($m, $theme . '/database/factories/ModelFactory', "database/factories/{$m->name}Factory.php", $force, $options)); } if ($option->tests) { $this->printif('Feature Test Controller', CodeGenerator::generate($m, $theme . '/tests/Feature/Http/Controllers/ModelControllerTest', "tests/Feature/Http/Controllers/{$m->name}ControllerTest.php", $force, $options)); if ($option->controller) { $this->printif('Feature Test Controller', CodeGenerator::generate($m, $theme . '/tests/Feature/Http/Controllers/ModelControllerTest', "tests/Feature/Http/Controllers/{$m->name}ControllerTest.php", $force, $options)); } if ($option->api) { $this->printif('Feature Test API Controller', CodeGenerator::generate($m, $theme . '/tests/Feature/Http/Controllers/API/ModelControllerTest', "tests/Feature/Http/Controllers/API/{$m->name}ControllerTest.php", $force, $options)); } } if ($option->notification) { $this->printif('Notification', CodeGenerator::generate($m, $theme . '/Notifications/ModelNotification', "app/Notifications/{$m->name}{$option->notification}.php", $force, $options)); } if ($option->event) { $this->printif('Event', CodeGenerator::generate($m, $theme . '/Events/ModelEvent', "app/Events/{$m->name}{$option->event}.php", $force, $options)); } if ($option->livewire) { $plural = str($m->name)->plural(); $this->printif('Livewire Component ', CodeGenerator::generate($m, "/livewire/Http/Index", "app/Http/Livewire/{$plural}/Index.php", $force, $options)); $this->printif('Livewire index view ', CodeGenerator::generate($m, "/livewire/views/index", "resources/views/livewire/{$folder}/index.blade.php", $force, $options)); $this->printif('Livewire list view ', CodeGenerator::generate($m, "/livewire/views/list", "resources/views/livewire/{$folder}/list.blade.php", $force, $options)); $this->printif('Livewire edit view ', CodeGenerator::generate($m, "/livewire/views/edit", "resources/views/livewire/{$folder}/edit.blade.php", $force, $options)); $this->printif('Livewire show view ', CodeGenerator::generate($m, "/livewire/views/show", "resources/views/livewire/{$folder}/show.blade.php", $force, $options)); } if ($option->routes) { $this->newLine(3); $this->line('<fg=cyan>'.CodeGenerator::generate($m, $theme . '/routes', null, $force, $options).'</>'); } $this->newLine(); $this->info('🎉 Finished!'); } public function printif($type, $filename) { $text = empty($filename) ? '<fg=red> ✖ </> '. $type . '<fg=yellow> already exists </>' : '<fg=green>✔</> <fg=default>' . $filename . '<fg=magenta> created. </>'; $this->line($text); } }
执行自定义命令
php artisan code:generator 'App\User' -FA
模板与自定义
模板位于 resources/vendor/laravel-code-generator
。例如,一旦您发布了视图,文件 schema.blade.json
将位于相对路径 resources/vendor/laravel-code-generator\schema.blade.json
。
resources/views/vendor/laravel-code-generator
路径是您可以创建自己的新模板或自定义现有模板的地方。
发布模板视图和配置
您可以发布
## views at: resources/views/vendor/laravel-code-generator php artisan vendor:publish --provider="VictorYoalli\LaravelCodeGenerator\LaravelCodeGeneratorServiceProvider" --tag="views"
或配置文件
## config file: config/laravel-code-generator.php php artisan vendor:publish --provider="VictorYoalli\LaravelCodeGenerator\LaravelCodeGeneratorServiceProvider" --tag="config"
这是已发布配置文件 config/laravel-code-generator.php
的内容
默认情况下,您可以使用以下扩展名的模板文件,如果您需要使用不同文件作为模板来生成或使用,则可以将其添加到配置文件中。
<?php return [ /** * Extension files that can be used with this Blade template engine. * You can add more if you need to. * .blade.php * .blade.js * .blade.jsx * .blade.vue * .blade.html * .blade.txt * .blade.json */ 'extensions' => [ 'js', 'jsx', 'vue', 'html', 'txt', 'json', ] ];
结构
- 模型 (对象)
- name (字符串)
- table (对象)
- relations (数组)
- 表 (对象)
- name (字符串)
- columns (数组)
- 列 (对象)
- name (字符串)
- type (字符串)
- length (整数)
- nullable (布尔值)
- autoincrement (布尔值)
- default (字符串)
- 关系 (数组)
- name (字符串)
- type (字符串)
- local_key (字符串)
- foreign_key (字符串)
- model (数组)
示例
{!!code()->PHPSOL()!!} namespace App\Http\Controllers\API; use App\{{$model->name}}; use Illuminate\Http\Request; use App\Http\Controllers\Controller; class {{$model->name}}Controller extends Controller { /** * Display a listing of the resource. * * @return \Illuminate\Http\Response */ public function index() { return {{$model->name}}::all(); } /** * Store a newly created resource in storage. * * @param \Illuminate\Http\Request $request * @return \Illuminate\Http\Response */ public function store(Request $request) { $this->validate($request, [ @foreach($model->table->columns as $col) @if(!str($col->name)->matches('/_at$/') && !str($col->name)->matches('/^id$/')) @if(!$col->nullable) '{{$col->name}}' => 'required', @endif @endif @endforeach ]); ${{str($model->name)->camel()}} = {{$model->name}}::create($request->all()); return ${{str($model->name)->camel()}}; } ... }
输出示例
<?php namespace App\Http\Controllers\API; use App\Models\User; use Illuminate\Http\Request; use App\Http\Controllers\Controller; class UserController extends Controller { /** * Display a listing of the resource. * * @return \Illuminate\Http\Response */ public function index() { return User::all(); } /** * Store a newly created resource in storage. * * @param \Illuminate\Http\Request $request * @return \Illuminate\Http\Response */ public function store(Request $request) { $this->validate($request, [ 'name' => 'required', 'email' => 'required', 'password' => 'required', ]); $user = User::create($request->all()); return $user; }
助手函数
PHPSOL()
:PHP行首
{!!code->PHPSOL()!!}
将打印
<?php
doubleCurlyOpen()
:打开双花括号
{{code()->doubleCurlyOpen()}}
将打印
{{
doubleCurlyClose()
:关闭双花括号
{{code()->doubleCurlyClose()}}
将打印
}}
tag('x-component-name')
:关闭双花括号
{{code()->tag('x-component-name')}}
将打印
<x-component-name>
CodeGenerator::generate Facade
这是当您想要创建自己的代码生成器时如何使用Facade的方法。
$filename = CodeGenerator::generate('App\Models\User', 'blade/show', "resources/views/{$folder}/show.blade.php", false); $generatedCodeString = CodeGenerator::generate($m, 'blade/routes' );
贡献
欢迎Pull requests。对于重大更改,请先打开一个问题以讨论您想要更改的内容。
请确保适当更新测试。