Custom Artisan commands
Importing products from a file, a mailing, cleaning up stale data — such tasks are started from the terminal or on a schedule rather than from a browser. You write your own Artisan commands for them: they have access to the whole application — models, mail, queues.
Creating
php artisan make:command SendWeeklyReportThe class appears in app/Console/Commands:
namespace App\Console\Commands;
use Illuminate\Console\Command;
class SendWeeklyReport extends Command
{
protected $signature = 'reports:send';
protected $description = 'Sends the weekly report to administrators';
public function handle(): int
{
$this->info('The report was sent.');
return self::SUCCESS;
}
}$signature is the name of the command, handle() is its work. Running it:
php artisan reports:sendArguments and options
Arguments and options are described right in $signature:
protected $signature = 'users:export {format} {--limit=100} {--active}';
public function handle(): int
{
$format = $this->argument('format');
$limit = (int) $this->option('limit');
$onlyActive = $this->option('active');
return self::SUCCESS;
}php artisan users:export csv --limit=500 --active| Form | Meaning |
|---|---|
{format} | A required argument |
{format?} | An optional argument |
{format=csv} | An argument with a default value |
{--active} | A flag: present or not |
{--limit=100} | An option with a value |
Output
$this->info('Done'); // green text
$this->warn('Careful'); // yellow
$this->error('Error'); // red
$this->line('A plain line');
$this->table(['Name', 'Email'], [['Anna', 'anna@example.com']]);Questions
$name = $this->ask('What should the file be called?');
if ($this->confirm('Delete the old records?')) {
// …
}
$format = $this->choice('Format', ['csv', 'json'], 0);A progress bar
Long operations show a progress bar:
$users = User::all();
$this->withProgressBar($users, function (User $user) {
$user->notify(new WeeklyDigest());
});Dependencies
The handle() method can ask for any service — the container supplies it:
public function handle(ReportBuilder $builder): int
{
$builder->build();
return self::SUCCESS;
}Running on a schedule and from code
use Illuminate\Support\Facades\Artisan;
use Illuminate\Support\Facades\Schedule;
Schedule::command('reports:send')->weeklyOn(1, '9:00');
Artisan::call('users:export', ['format' => 'csv', '--limit' => 50]);Common mistake
A command must return an exit code: self::SUCCESS on success and self::FAILURE on an error. The scheduler and deployment systems use it to tell whether the operation worked. A command that silently returns success on failure hides the problem.
if (!$file) {
$this->error('File not found.');
return self::FAILURE;
}