effiana/cron
A Laravel package for managing and running cron-style scheduled tasks within your application. Define jobs, configure timing, and trigger execution from the CLI or scheduler, providing a simple way to centralize recurring task automation in Laravel.
Installation
composer require effiana/cron
Add the service provider to config/app.php:
Effiana\Cron\CronServiceProvider::class,
Publish Config
php artisan vendor:publish --provider="Effiana\Cron\CronServiceProvider" --tag="config"
This generates config/cron.php with default settings.
Define a Job
Create a job class (e.g., app/Jobs/ProcessReport.php):
namespace App\Jobs;
use Effiana\Cron\Contracts\JobInterface;
class ProcessReport implements JobInterface
{
public function run()
{
// Your logic here
}
}
Register the Job
Add the job to config/cron.php under jobs:
'jobs' => [
'process-report' => [
'class' => \App\Jobs\ProcessReport::class,
'schedule' => '0 0 * * *', // Runs daily at midnight
],
],
Run the Scheduler
Add a command to your app/Console/Kernel.php:
protected function schedule(Schedule $schedule)
{
$schedule->command('cron:run')->everyMinute();
}
Then run:
php artisan schedule:run
Extend JobInterface to log execution:
use Effiana\Cron\Contracts\JobInterface;
use Illuminate\Support\Facades\Log;
class LogTest implements JobInterface
{
public function run()
{
Log::info('Cron job executed at: ' . now());
}
}
Register it in config/cron.php:
'jobs' => [
'log-test' => [
'class' => \App\Jobs\LogTest::class,
'schedule' => '* * * * *', // Runs every minute
],
],
use Effiana\Cron\Facades\Cron;
Cron::addJob('dynamic-job', \App\Jobs\DynamicJob::class, '*/5 * * * *');
.env:
CRON_JOBS=backup-database=0 3 * * *,clean-logs=0 4 * * *
Parse in a service provider:
$jobs = explode(',', env('CRON_JOBS'));
foreach ($jobs as $job) {
[$name, $schedule] = explode('=', $job);
Cron::addJob($name, \App\Jobs\BackupDatabase::class, $schedule);
}
after() to chain jobs:
Cron::addJob('job-a', \App\Jobs\JobA::class, '*/10 * * * *')
->after('job-b');
shouldRun() in your job:
class ConditionalJob implements JobInterface
{
public function shouldRun(): bool
{
return config('app.maintenance_mode') === false;
}
public function run() { ... }
}
app/Exceptions/Handler.php:
public function register()
{
$this->renderable(function (Throwable $e, $request) {
if ($e instanceof \Effiana\Cron\Exceptions\JobException) {
Log::error('Cron job failed: ' . $e->getMessage());
}
});
}
use Illuminate\Support\Facades\Bus;
Bus::dispatchNow((new \App\Jobs\RetryableJob())->retryUntil(3));
JobInterface to use queues:
use Illuminate\Bus\Queueable;
class QueuedJob implements JobInterface
{
use Queueable;
public function run() { ... }
}
Cron::addJob('queue-job', \App\Jobs\QueuedJob::class, '*/5 * * * *');
$this->app->singleton(\Psr\Log\LoggerInterface::class, function () {
return new \Monolog\Logger('cron', [
new \Monolog\Handler\StreamHandler(storage_path('logs/cron.log')),
]);
});
run():
$start = microtime(true);
// Job logic
Log::info('Job took ' . (microtime(true) - $start) . ' seconds');
config/app.php timezone matches your server’s timezone. Cron schedules are evaluated in the server’s timezone by default.config/cron.php is published and properly structured. Default config may not include all keys.last_run_at column to a jobs table and log it in run():
public function run()
{
\DB::table('jobs')->where('name', 'log-test')->update([
'last_run_at' => now(),
]);
}
'debug' => true in config/cron.php to log schedule evaluations.dispatchSync() sparingly.DB::transaction(function () {
// Job logic
});
Effiana\Cron\Schedule class to support custom syntax (e.g., "every 90 minutes").\Effiana\Cron\Events\JobStarting::class,
\Effiana\Cron\Events\JobCompleted::class,
$schedule = \App\Models\CronSchedule::where('job_name', 'dynamic-job')->first()->cron_expression;
Cron::addJob('dynamic-job', \App\Jobs\DynamicJob::class, $schedule);
php artisan schedule:run is in your server’s cron (e.g., * * * * * cd /path-to-project && php artisan schedule:run >> /dev/null 2>&1).php artisan queue:work).illuminate/support and illuminate/console are installed (this package relies on Laravel’s core).Schedule facade in tests:
public function test_cron_job()
{
$this->app->make(\Effiana\Cron\CronManager::class)->addJob('test-job', \App\Jobs\TestJob::class, '* * * * *');
$this->app->make(\Illuminate\Console\Scheduling\Schedule::class)->call('test-job');
// Assertions
}
travel() to test schedules:
use Illuminate\Foundation\Testing\TimeTravelsTo;
class CronTest extends TestCase
{
use TimeTravelsTo;
public function test_scheduled_job()
{
$this->travelTo(now()->addMinutes(1));
$this->app->make(\Effiana\Cron\CronManager::class)->runPending();
// Assert job ran
}
}
How can I help you explore Laravel packages today?