Victoryoalli/laravel-code-generator

用于代码生成的PHP包。

4.0.0 2023-03-14 16:57 UTC

README

GitHub release (latest by date) Packagist PHP Version Support GitHub forks GitHub stars Packagist Downloads

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。对于重大更改,请先打开一个问题以讨论您想要更改的内容。

请确保适当更新测试。

许可证

MIT