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
That would generate this class:
<?php
namespace App\Actions;
class SendSalaries extends BaseAction
{
public function run()
{
// TODO: Implement run() method.
}
}
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.
}
}
Then we will need to create a new make:action
command.
php artisan make:command ActionMakeCommand
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
{
....
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
{
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;
}
- 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';
}
- Set property
$type
to 'Action'. This is intended for the console display.
protected $type = 'Action';
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;
...
And add the --test
option when calling the make command:
php artisan make:action --test CreateSubscription
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)