DEV Community

Cover image for Create your own laravel make commands
Ramy
Ramy

Posted on

Create your own laravel make commands

So for those of you who like to extend your laravel application. You may already know that you can customize the default stubs of the artisan make:* commands by calling the command artisan stub:publish and customizing the files in the stubs folder.

So what I would really want is to create my own maker command for non-framework classes.
Let's say I usually use Action* classes in my laravel project. I would really want to have a command that would streamline the process of creating such classes. Example:

php artisan make:action SendSalaries
Enter fullscreen mode Exit fullscreen mode

That would generate this class:

<?php

namespace App\Actions;


class SendSalaries extends BaseAction
{
    public function run()
    {
        // TODO: Implement run() method.
    }
}
Enter fullscreen mode Exit fullscreen mode

Actions classes are a concept regularly used among laravel developers. See freek.dev blog post.

Implementation

Let's start by adding a new stub file action.stub:

<?php

namespace {{ namespace }};


class {{ class }} extends BaseAction
{
    public function run()
    {
        // TODO: Implement run() method.
    }
}
Enter fullscreen mode Exit fullscreen mode

Then we will need to create a new make:action command.

php artisan make:command ActionMakeCommand
Enter fullscreen mode Exit fullscreen mode

And replace the base command class by the abstract command GeneratorCommand. This class is used by the laravel framework to create make commands.

use Illuminate\Console\GeneratorCommand;


class ActionMakeCommand extends GeneratorCommand
{
  ....

Enter fullscreen mode Exit fullscreen mode

After that it's pretty straightforward. We'll need to make these little changes:

  • Add the php attribute #[AsCommand(name: 'make:action')].
use Symfony\Component\Console\Attribute\AsCommand;

#[AsCommand(name: 'make:action')
class ActionMakeCommand extends GeneratorCommand
{
Enter fullscreen mode Exit fullscreen mode

Since version 9, the Laravel framework no longer maintains support for PHP 7.

  • Implement the getStub() method so that it returns the action stub file.
protected function getStub()
{
    return $this->resolveStubPath('/stubs/action.stub');
}

protected function resolveStubPath($stub)
{
    return file_exists($customPath = $this->laravel->basePath(trim($stub, '/')))
        ? $customPath
        : __DIR__.$stub;
}
Enter fullscreen mode Exit fullscreen mode
  • Extend the getDefaultNamespace method in order to specify the target file location. Otherwise, the generated classes will be placed at the project's root.
protected function getDefaultNamespace($rootNamespace)
{
    return $rootNamespace . '\Actions';
}
Enter fullscreen mode Exit fullscreen mode
  • Set property $type to 'Action'. This is intended for the console display.
protected $type = 'Action';
Enter fullscreen mode Exit fullscreen mode

What about generating a test class?

Simple ! We just have to include the CreatesMatchingTest trait:

...
use Illuminate\Console\Concerns\CreatesMatchingTest;

class ActionMakeCommand extends GeneratorCommand
{
    use CreatesMatchingTest;
    ...
Enter fullscreen mode Exit fullscreen mode

And add the --test option when calling the make command:

php artisan make:action --test CreateSubscription
Enter fullscreen mode Exit fullscreen mode

What did we learn?

We've learned that alongside customizing default stubs in Laravel, crafting your own generator is remarkably straightforward. By developing a command that extends the GeneratorCommand and associating it with your cutomized stub file, the process becomes seamless.
Credit is due to the laravel team for doing a great job designing the command generator, enabling such ease and flexibility in customization.

*: For the sake of simplicity I've used an action as an example but generally there is no need to make a maker command for a plain class.

**: Cover image

Top comments (0)