<?php
namespace App\Console\Commands;
use App\Models\User;
use App\Notifications\NewsletterEmail;
use Illuminate\Console\Command;
use Illuminate\Support\Facades\Notification;
class SendNewsletter extends Command
{
protected $signature = 'newsletter:send
{--type=weekly : Newsletter type}
{--dry-run : Preview without sending}';
protected $description = 'Send newsletter to all subscribers';
public function handle(): int
{
$type = $this->option('type');
$dryRun = $this->option('dry-run');
$this->info("Preparing {$type} newsletter...");
$subscribers = User::whereNotNull('subscribed_at')->get();
if ($subscribers->isEmpty()) {
$this->warn('No subscribers found');
return self::FAILURE;
}
$this->info("Found {$subscribers->count()} subscribers");
if ($dryRun) {
$this->warn('Dry run mode - no emails will be sent');
return self::SUCCESS;
}
if (!$this->confirm('Send newsletter to all subscribers?')) {
$this->error('Newsletter cancelled');
return self::FAILURE;
}
$bar = $this->output->createProgressBar($subscribers->count());
$bar->start();
foreach ($subscribers as $subscriber) {
Notification::send($subscriber, new NewsletterEmail($type));
$bar->advance();
}
$bar->finish();
$this->newLine();
$this->info('Newsletter sent successfully!');
return self::SUCCESS;
}
}
<?php
namespace App\Console\Commands;
use App\Models\Post;
use Illuminate\Console\Command;
class GenerateReport extends Command
{
protected $signature = 'report:generate
{period : Report period (daily|weekly|monthly)}
{--format=table : Output format (table|json)}';
protected $description = 'Generate analytics report';
public function handle(): int
{
$period = $this->argument('period');
$format = $this->option('format');
$stats = $this->gatherStats($period);
if ($format === 'json') {
$this->line(json_encode($stats, JSON_PRETTY_PRINT));
} else {
$this->table(
['Metric', 'Value'],
[
['Total Posts', $stats['total_posts']],
['Published', $stats['published']],
['Total Views', number_format($stats['total_views'])],
['Avg Views', number_format($stats['avg_views'], 2)],
]
);
}
return self::SUCCESS;
}
private function gatherStats(string $period): array
{
$query = Post::query();
if ($period === 'daily') {
$query->whereDate('created_at', today());
}
return [
'total_posts' => $query->count(),
'published' => $query->whereNotNull('published_at')->count(),
'total_views' => $query->sum('views'),
'avg_views' => $query->avg('views'),
];
}
}
Artisan commands automate repetitive tasks via the command line. I create command classes with php artisan make:command defining signatures and descriptions. The handle() method contains command logic. Arguments and options capture user input with type hints and defaults. Commands output via $this->info(), $this->error(), and $this->table(). I call other commands with $this->call() for composition. Scheduled commands in Kernel.php run via cron. Progress bars visualize long operations. Command testing uses artisan() helper. Custom commands handle database maintenance, data imports, cache warming, or business processes. They're essential for DevOps and automation workflows.