Install the Package
composer require byfareska/cron-bundle
Add to config/bundles.php if not auto-discovered:
return [
// ...
Byfareska\CronBundle\ByfareskaCronBundle::class => ['all' => true],
];
Configure the Cron Job
Add this line to your system's crontab (e.g., /etc/crontab or via crontab -e):
* * * * * php /path/to/your/project/bin/console cron:run
Replace /path/to/your/project with your Laravel project root.
Create Your First Task
Implement ScheduledTask in a service class:
namespace App\Tasks;
use Byfareska\Cron\Task\ScheduledTask;
use DateTimeInterface;
use Symfony\Component\Console\Output\OutputInterface;
final class CleanupOldLogsTask implements ScheduledTask
{
public function cronInvoke(DateTimeInterface $now, bool $forceRun, OutputInterface $output): bool
{
// Run daily at midnight
if ($forceRun || $now->format('H:i') === '00:00') {
$this();
$output->writeln('Cleanup logs executed at ' . $now->format('Y-m-d H:i:s'));
return true;
}
return false;
}
public function __invoke(): void
{
// Your cleanup logic here
}
}
Tag the Task for Auto-Discovery
Register the task as a service with the cron.task tag in config/services.php:
return [
// ...
'tags' => [
'cron.task' => [
App\Tasks\CleanupOldLogsTask::class,
// Add other tasks here
],
],
];
Test Manually Run the cron command manually to verify:
php artisan cron:run
Conditional Execution
Use cronInvoke() to control when tasks run based on:
format('i') === '0' for hourly tasks).$forceRun for manual triggers).Example: Run a backup task every 3 hours:
public function cronInvoke(DateTimeInterface $now, bool $forceRun, OutputInterface $output): bool
{
if ($forceRun || $now->format('G') % 3 === 0) {
$this();
return true;
}
return false;
}
Dependency Injection Inject services (e.g., repositories, HTTP clients) into your task:
final class SendDailyReportTask implements ScheduledTask
{
public function __construct(
private readonly ReportService $reportService,
private readonly Mailer $mailer
) {}
public function cronInvoke(DateTimeInterface $now, bool $forceRun, OutputInterface $output): bool
{
if ($forceRun || $now->format('H') === '09') { // 9 AM daily
$this();
return true;
}
return false;
}
public function __invoke(): void
{
$report = $this->reportService->generate();
$this->mailer->send($report);
}
}
Output Handling
Use OutputInterface to log task execution:
$output->writeln('Task started at ' . $now->format('Y-m-d H:i:s'));
$output->section('Processing data...');
$output->writeln('Task completed successfully.');
Error Handling Wrap task logic in try-catch and log errors:
public function __invoke(): void
{
try {
// Risky operations
} catch (\Throwable $e) {
$output->writeln('<error>Task failed: ' . $e->getMessage() . '</error>');
// Optionally rethrow or log to a monitoring service
}
}
Development Workflow
php artisan cron:run --task=YourTask to test tasks without waiting for cron.--verbose or --debug flags to the cron command for detailed output.DRY_RUN environment variable to skip actual operations:
if (env('DRY_RUN')) {
$output->writeln('<comment>Skipping execution (dry run mode)</comment>');
return true;
}
Deployment Workflow
TaskRegistry service to dynamically register tasks (advanced):
$container->register(
new Definition(CleanupOldLogsTask::class),
['tags' => ['cron.task']]
);
Task Scheduling
public function cronInvoke(DateTimeInterface $now, bool $forceRun, OutputInterface $output): bool
{
$isWeekday = $now->format('N') <= 5; // Monday=1, Sunday=7
$isBusinessHour = $now->format('H') >= 9 && $now->format('H') <= 17;
if ($forceRun || ($isWeekday && $isBusinessHour && $now->format('i') === '0')) {
$this();
return true;
}
return false;
}
Integration with Laravel
public function register()
{
$this->app->tag([
App\Tasks\CleanupOldLogsTask::class,
], 'cron.task');
}
php artisan cron:run --task=YourTask --force
Cron Job Timing
format('i') <= 2 for "every 2 minutes") or implement a "missed run" check:
public function cronInvoke(DateTimeInterface $now, bool $forceRun, OutputInterface $output): bool
{
$lastRun = $this->storage->getLastRunTime();
if ($forceRun || ($now->getTimestamp() - $lastRun->getTimestamp()) >= 3600) { // 1 hour
$this();
$this->storage->setLastRunTime($now);
return true;
}
return false;
}
Task Registration
php artisan debug:container --tag=cron.task
$this->app->tag([YourDynamicTask::class], 'cron.task');
Output Buffering
* * * * * php /path/to/your/project/bin/console cron:run >> /var/log/cron.log 2>&1
Time Zone Handling
DateTimeInterface uses the system time zone by default.$now = new DateTime('now', new DateTimeZone('America/New_York'));
Long-Running Tasks
OutputInterface or a logger (e.g., Monolog) to track task execution:
$output->writeln('Task started');
try {
$this();
$output->writeln('Task succeeded');
} catch (\Throwable $e) {
$output->w
How can I help you explore Laravel packages today?