A Laravel package that enables database-driven task scheduling, allowing you to manage scheduled commands dynamically without modifying code or redeploying your application.
In traditional Laravel applications, scheduled tasks must be defined in the app/Console/Kernel.php file:
protected function schedule(Schedule $schedule)
{
$schedule->command('emails:send')->daily();
$schedule->command('reports:generate')->weekly();
$schedule->command('backup:run')->dailyAt('01:00');
}This static approach has several limitations:
- Requires Code Changes: Every schedule modification needs code changes and redeployment
- No Runtime Flexibility: Cannot add, modify, or disable schedules without deploying
- Lacks Dynamic Control: Difficult to implement user-defined or tenant-specific schedules
- No Easy Management: No built-in UI or database interface for schedule management
Laravel BluSchedule solves these problems by storing scheduled commands in the database, enabling you to:
✅ Add, modify, or remove schedules without touching code
✅ Enable/disable schedules dynamically using status flags
✅ Manage schedules through admin panels or APIs
✅ Implement tenant-specific or user-defined schedules
✅ Use all Laravel's built-in frequency methods or custom cron expressions
- Database-Driven Scheduling: Store all schedule definitions in the
blu_schedulestable - Active/Inactive Status: Enable or disable schedules without deletion
- Flexible Frequencies: Support for all Laravel frequency methods (
everyMinute(),hourly(),daily(), etc.) - Custom Cron Expressions: Use custom cron syntax for advanced scheduling
- Parameter Support: Pass parameters to commands and frequency methods
- Zero Configuration: Auto-discovery and auto-migration via Laravel package discovery
Install the package via Composer:
composer require abedi/bluscheduleThe package uses Laravel's auto-discovery feature, so the service provider will be automatically registered.
Run the migration to create the blu_schedules table:
php artisan migrateMake sure your system cron is configured to run Laravel's scheduler every minute:
* * * * * cd /path-to-your-project && php artisan schedule:run >> /dev/null 2>&1The migration creates a blu_schedules table with the following structure:
| Column | Type | Description |
|---|---|---|
id |
bigint | Primary key |
name |
string | Descriptive name for the schedule |
command |
string | Artisan command name (e.g., emails:send) |
frequency |
string | Frequency method or cron expression |
frequency_params |
json | Parameters for frequency method (nullable) |
params |
json | Parameters for the command (nullable) |
status |
enum | ACTIVE or DEACTIVE |
created_at |
timestamp | Creation timestamp |
updated_at |
timestamp | Last update timestamp |
Insert a schedule into the database:
use Abedi\BluSchedule\Models\Schedule;
use Abedi\BluSchedule\Concerns\ScheduleStatusEnum;
Schedule::create([
'name' => 'Send Daily Emails',
'command' => 'emails:send',
'frequency' => 'daily',
'status' => ScheduleStatusEnum::ACTIVE,
]);That's it! The command will now run daily without any code changes.
Schedule::create([
'name' => 'Generate Monthly Report',
'command' => 'reports:generate',
'params' => ['--type=monthly', '--format=pdf'],
'frequency' => 'monthly',
'status' => ScheduleStatusEnum::ACTIVE,
]);Schedule::create([
'name' => 'Backup Database at 2 AM',
'command' => 'backup:run',
'frequency' => 'dailyAt',
'frequency_params' => ['02:00'],
'status' => ScheduleStatusEnum::ACTIVE,
]);Schedule::create([
'name' => 'Custom Schedule',
'command' => 'custom:task',
'frequency' => '0 */4 * * *', // Every 4 hours
'status' => ScheduleStatusEnum::ACTIVE,
]);$schedule = Schedule::find(1);
$schedule->status = ScheduleStatusEnum::DEACTIVE;
$schedule->save();'everySecond'
'everyTwoSeconds'
'everyFiveSeconds'
'everyTenSeconds'
'everyFifteenSeconds'
'everyTwentySeconds'
'everyThirtySeconds'
'everyMinute'
'everyTwoMinutes'
'everyThreeMinutes'
'everyFourMinutes'
'everyFiveMinutes'
'everyTenMinutes'
'everyFifteenMinutes'
'everyThirtyMinutes'
'hourly'
'everyTwoHours'
'daily'
'weekly'
'monthly'
'quarterly'
'yearly''hourlyAt' => ['17'] // Run at 17 minutes past the hour
'dailyAt' => ['13:00'] // Run daily at 1:00 PM
'twiceDaily' => [1, 13] // Run at 1:00 AM and 1:00 PM
'twiceDailyAt' => [1, 13, 15] // Run at 1:15 AM and 1:15 PM
'weeklyOn' => [1, '8:00'] // Run weekly on Monday at 8:00 AM
'monthlyOn' => [4, '15:00'] // Run on the 4th of each month at 3:00 PM
'twiceMonthly' => [1, 16, '13:00'] // Run on 1st and 16th at 1:00 PM
'quarterlyOn' => [4, '14:00'] // Run on 4th of each quarter at 2:00 PM
'yearlyOn' => [6, 1, '17:00'] // Run on June 1st at 5:00 PMFor any frequency not listed above, you can use standard cron syntax:
'frequency' => '0 0 * * 0' // Every Sunday at midnight
'frequency' => '*/15 * * * *' // Every 15 minutes
'frequency' => '0 9-17 * * 1-5' // Weekdays 9 AM to 5 PMThe package uses a smart detection mechanism in its ServiceProvider:
- Detects Schedule Commands: When any
schedule:*artisan command runs (e.g.,schedule:run,schedule:list) - Loads Active Schedules: Queries the database for all schedules with
ACTIVEstatus - Registers Dynamically: Registers each schedule with Laravel's scheduler using the same API
- Executes Normally: Laravel's scheduler handles execution timing and running the commands
This approach ensures zero performance impact on non-scheduling operations and seamless integration with Laravel's existing scheduler.
// Get schedule ID
$schedule->getId(): int
// Get schedule name
$schedule->getName(): string
// Get command name
$schedule->getCommand(): string
// Get frequency
$schedule->getFrequency(): string
// Get frequency parameters
$schedule->getFrequencyParams(): array
// Get command parameters
$schedule->getParams(): array
// Get status
$schedule->getStatus(): ScheduleStatusEnum
// Check if using custom cron expression
$schedule->isCustomFrequency(): bool// Good
'name' => 'Send Weekly Newsletter to Subscribers'
// Bad
'name' => 'Task 1'// Good - Can be re-enabled later
$schedule->status = ScheduleStatusEnum::DEACTIVE;
// Less flexible - Data is lost
$schedule->delete();Before scheduling, test your commands manually:
php artisan emails:send --type=weeklyUse Laravel's built-in schedule commands:
# List all scheduled tasks
php artisan schedule:list
# Test the schedule without running tasks
php artisan schedule:testprotected function handle()
{
$this->info('Starting email send process...');
// Your logic here
$this->info('Email send process completed.');
}Different tenants can have different schedules:
Schedule::create([
'name' => 'Tenant A Daily Report',
'command' => 'tenant:report',
'params' => ['--tenant=a'],
'frequency' => 'daily',
'status' => ScheduleStatusEnum::ACTIVE,
]);
Schedule::create([
'name' => 'Tenant B Weekly Report',
'command' => 'tenant:report',
'params' => ['--tenant=b'],
'frequency' => 'weekly',
'status' => ScheduleStatusEnum::ACTIVE,
]);Build an admin interface to manage schedules:
// Controller method
public function updateSchedule(Request $request, $id)
{
$schedule = Schedule::findOrFail($id);
$schedule->update($request->validated());
return redirect()->back()->with('success', 'Schedule updated!');
}Enable schedules for specific periods:
// Enable promotion task during campaign
$schedule = Schedule::create([
'name' => 'Black Friday Promotion Emails',
'command' => 'promotions:send',
'frequency' => 'hourly',
'status' => ScheduleStatusEnum::ACTIVE,
]);
// Disable after campaign ends
$schedule->update(['status' => ScheduleStatusEnum::DEACTIVE]);- PHP 8.2 or higher
- Laravel 11.0 or higher
This package is open-source software. Please check the LICENSE file for more information.
- Author: Mehdi Abedi
- Email: [email protected]
- Package:
abedi/bluschedule
Contributions are welcome! Please feel free to submit a Pull Request.
If you encounter any issues or have questions, please open an issue on the GitHub repository.
Transform your Laravel scheduling from static code to dynamic database control with BluSchedule! 🚀