laravel / ideas

Issues board used for Laravel internals discussions.
939 stars 28 forks source link

Make more flexible namespace resolution for GeneratorCommand (artisan make:cmd) #1854

Open Insolita opened 5 years ago

Insolita commented 5 years ago

The general problem is if we want to use project structure that different from default conventions - more modular, for example - generator usage become a pain. We forced to write full qualified namespaces with additional slash escaping every time. I know about existed https://github.com/nWidart/laravel-modules package - but it not support all available generators, and not support generators for third-party extensions, for example Nova. And there only one way for override default namespace resolving for Commands based on GeneratorCommand - is override each command. That sounds not well for me. I would better preffer to have some config file with my overrides like:

    'defaults' => [
        'make:model' => 'App\Models',
        'make:command' => 'Acme\CurrentBundle\Commands',
       //...
    ],
    'ns' => [
        'dash' => 'App\Modules\Dashboard',
        'orders' => 'Custom\Package\Orders',
        //...
    ],

And use it as artisan make:model User --> should create App\Models\User

artisan make:rule MyRule --on dash -->should create App\Modules\Dashboard\Rules\MyRule

artisan nova:filter DeliveryFilter --on orders -->should create Custom\Package\Orders\Nova\Filters\DeliveryFilter

I had an idea to intercept artisan command calls and extend name argument accordingly my configuration, with

use Illuminate\Console\Events\CommandStarting;
Event::listen(CommandStarting::class, function(CommandStarting $event){
      $args = $event->input->getArguments();
      dump($args) --> empty!!! 
});

Unfortunately, this event is not enough for us, because it fires before command definition binding https://github.com/laravel/framework/blob/6.x/src/Illuminate/Console/Application.php#L84

Best placement should be in place when Symfony fired own event https://github.com/symfony/symfony/blob/3.4/src/Symfony/Component/Console/Application.php#L997 But laravel doesn't support symfony console events.

So my idea implementation is impossible now. :cry:

Finally, there are several ways for solution:

btw: also the laravel-modules has interesting feature for remember/forget current module namespace for next usages with make:use namespace | make:unuse namespace.

hubertnnn commented 5 years ago

I personally think that the make:xxx commands need a big rework.

First thing is that they need a way to modify the templates. Lets say that I want all my models to extend some base model class, or all controllers to extend a base controller. Maybe I want to automatically add copyrights comment in all files etc. This could be done by using blade to generate the files and overwrite templates in project.

Second thing is that they should not be a part of framework core in the first place. Since Laravel is recently splitting more and more components into separate modules like eg. Helper methods, or HTML form generators, make:xxx commands should also go to a separate package. Not only that, but the package should be included only as dev. Reasoning is that not everyone uses it, and on top of that, you dont really need those commands in your production. They only waste space in artisan help screen there.

Last thing is the one you mentioned, that the commands need some extra configuration options. Things like location of generated file or optional parameters as a few examples. Maybe even a way to easily overwrite the logic of a specific make:xxx command in project to make it more fitting.

crynobone commented 4 years ago

I just released orchestra/canvas which bring make:** command to Laravel and Laravel Packages. This would bring all the make command to package development (we're using Symfony Command) under the hood.

As for Laravel, you should be able to customize the configuration using canvas.yaml which should sit at the root directory (same level as composer.json).

preset: laravel

namespace: App

model:
  namespace: App

If you want to customize the model namespace, just change it to

model:
  namespace: App\Model