Create make:custom commands in Laravel
Mar 4, 2022
Laravel comes with a feature that allows us to scaffold some commonly used classes, like models, factories, notifications, etc. If we want to create a model, for example, we can do it by running:
php artisan make:model MyModel
But what if we could do this for our custom classes? Instead of copying and pasting code, why don't we automate that process with a simple command!?. In this article, I'll show you how to do that exactly.
Let's start at the end
Before we start, we need to think about what we are building. I want to make a command that creates an empty report class that extends a different imaginary Report
class.
I would like to run a command like this:
php artisan make:report MonthlyReport
That would then create a class under app/Reports/
with the following content:
<?php
namespace App\Reports;
class MontlyReport extends Report
{
public function generate()
{
// TODO: add code..
}
}
Of course, your classes don't have to be exactly like mine, you can use what I'm going to show you to make a generator command that fits your needs.
Generating a generator command
First, we need to create the command that will handle the generation of the classes. Make a new command with:
php artisan make:command MakeReport
I named my command MakeReport
you can name it whatever you think fits better for your use case.
After that, we can find it under app/Console/Commands/
. Open the file and change the extended class from Command
to GeneratorCommand
.
While we are here, we should also change the signature to make:report {name}
(replace "report" with your type).
<?php
namespace App\Console\Commands;
use Illuminate\Console\GeneratorCommand;
class MakeReport extends GeneratorCommand
{
/**
* The name and signature of the console command.
*
* @var string
*/
protected $signature = 'make:report {name}';
...
}
We'll come back to this command later. Before that, let's create the template for our class.
Adding the class template
To create the template for our classes, we need to create a new folder under app/Console/Commands
named Stubs
. Inside this folder, we need to create a new text file that contains the template for our class. I made a file with the name make-report.stub
, and in that file, I added the template for the class:
<?php
namespace App\Reports;
class DummyReport extends Report
{
public function generate()
{
// TODO: add code..
}
}
The DummyReport
name for the class is just a placeholder for the real class name. You can set it to whatever you want, but remember what it is since we'll replace it in the next step.
The generation logic
Now inside the get MakeReport
command that we created earlier, I deleted every method and overwrote three new methods getStub
getDefaultNamespace
and replaceClass
class MakeReport extends GeneratorCommand
{
/**
* The name and signature of the console command.
*
* @var string
*/
protected $signature = 'make:report {name}';
//...
public function getStub()
{
return app_path() . '/Console/Commands/Stubs/make-report.stub';
}
public function getDefaultNamespace($rootNamespace)
{
return $rootNamespace . '\Reports';
}
public function replaceClass($stub, $name)
{
$stub = parent::replaceClass($stub, $name);
return str_replace("DummyReport", $this->argument('name'), $stub);
}
}
In the first method, we define the path to our stub file. In the second one, we add the namespace of the generated command, in this case, it will be App\Reports
. The namespace will be used to calculate the correct path of the new class. And in the last method, we replace the DummyReport
class name with the actual class name sent as an argument to the command.
The final result
And that is it. Now we have a command to generate our custom class by simply running this in the terminal:
php artisan make:report MyReport
And a new report will be created automatically.
If you liked this article follow me on Twitter, I post tips and other laravel content there.
You might also like