zpm-packages / cron-manager
A PHP package for managing cron jobs on Unix-like systems and Windows Task Scheduler
Requires
- php: ^8.0
Requires (Dev)
- phpunit/phpunit: ^10.0
README
A clean and easy-to-use PHP package for managing scheduled jobs on Unix-like systems through crontab and on Windows through Task Scheduler. The package allows you to programmatically add, update, remove, and list jobs with support for both standard cron expressions and human-readable schedules.
Features
- ✅ List managed cron jobs with standard cron times and human-readable descriptions
- ✅ Add new cron jobs using standard cron format or human-readable expressions
- ✅ Update existing cron jobs
- ✅ Remove cron jobs
- ✅ Automatic adapter selection for Unix
crontabor Windows Task Scheduler - ✅ Shared preset schedule options and command tips for Laravel and Filament integrations
- ✅ Clean, object-oriented API
- ✅ Comprehensive test coverage
Requirements
- PHP 8.0 or higher
- On Linux or macOS: the
crontabcommand available in PATH - On Windows: PowerShell Task Scheduler cmdlets available
Installation
composer require zpm-packages/cron-manager
Reusable Schedule Presets
The package exposes reusable schedule suggestions and a command tip string that can be shared by UIs and wrappers:
use ZPMPackages\CronManager\Support\ScheduleOptions; $scheduleOptions = ScheduleOptions::selectOptions(); $windowsSafeOptions = ScheduleOptions::selectOptions(true); $commandTip = ScheduleOptions::commandTip('/schedule.php');
Use the full option set on Unix-like systems, or the Windows-safe set when you only want presets that the Task Scheduler adapter can translate directly.
Quick Test Script
The package includes a small schedule.php helper script for smoke testing commands:
php /schedule.php "Cron comment"
Expected output:
Cron comment ran at 2026-05-06 13:45:00
Script contents:
<?php $comment = $argv[1] ?? 'Cron comment'; echo sprintf('%s ran at %s%s', $comment, date('Y-m-d H:i:s'), PHP_EOL);
Usage
Basic Example
<?php require 'vendor/autoload.php'; use ZPMPackages\CronManager\CronManager; use ZPMPackages\CronManager\CronJob; // Create a new CronManager instance $manager = new CronManager(); // List all cron jobs $crons = $manager->listCrons(); foreach ($crons as $cron) { echo "Schedule: " . $cron->getSchedule() . "\n"; echo "Command: " . $cron->getCommand() . "\n"; echo "Comment: " . ($cron->getComment() ?? 'N/A') . "\n"; echo "---\n"; }
List Cron Jobs with Human-Readable Schedules
$crons = $manager->listCronsWithHumanReadable(); foreach ($crons as $cron) { echo "Schedule: " . $cron['schedule'] . "\n"; echo "Human-readable: " . $cron['human_readable'] . "\n"; echo "Command: " . $cron['job']->getCommand() . "\n"; echo "---\n"; }
Add Cron Jobs
Using Human-Readable Expressions
// Add a cron job that runs every minute $manager->addCron('every minute', 'php /schedule.php "Cron comment"', 'Cron comment'); // Add a cron job that runs every hour $manager->addCron('every hour', '/usr/bin/php /path/to/script.php', 'Hourly task'); // Add a cron job that runs every day at midnight $manager->addCron('every day', '/usr/bin/backup.sh', 'Daily backup'); // Add a cron job with custom interval $manager->addCron('every 5 minutes', '/usr/bin/php /path/to/script.php'); $manager->addCron('every 2 hours', '/usr/bin/php /path/to/script.php'); $manager->addCron('every 3 days', '/usr/bin/php /path/to/script.php');
Using Standard Cron Format
// Standard cron format: minute hour day month weekday $manager->addCron('0 0 * * *', '/usr/bin/php /path/to/script.php', 'Daily at midnight'); $manager->addCron('*/15 * * * *', '/usr/bin/php /path/to/script.php', 'Every 15 minutes'); $manager->addCron('0 9 * * 1', '/usr/bin/php /path/to/script.php', 'Every Monday at 9 AM');
Using CronJob Object
$cronJob = new CronJob( '0 0 * * *', '/usr/bin/php /path/to/script.php', 'Daily backup' ); $manager->addCron($cronJob);
Update Cron Jobs
// Get all cron jobs $crons = $manager->listCrons(); // Update the first cron job (index 0) $manager->updateCron(0, 'every hour', '/usr/bin/php /path/to/new_script.php', 'Updated job'); // Or update using CronJob object $updatedJob = new CronJob('0 */2 * * *', '/usr/bin/php /path/to/script.php', 'Every 2 hours'); $manager->updateCron(0, $updatedJob);
Remove Cron Jobs
// Remove a specific cron job by index $crons = $manager->listCrons(); $manager->removeCron(0); // Remove the first cron job // Remove all cron jobs $manager->removeAllCrons();
Windows Task Scheduler
$manager = new CronManager(); // On Windows the package automatically uses Task Scheduler. $manager->addCron('every hour', 'php C:\\projects\\app\\schedule.php "Cron comment"', 'Cron comment');
The Windows adapter stores and manages the tasks that it creates through Task Scheduler. The current Windows implementation supports these schedules:
* * * * **/N * * * *0 * * * *0 */N * * *0 0 * * *0 0 */N * *0 0 * * 0
Monthly, yearly, and more complex cron expressions should be managed on Unix-like systems or translated into a supported Windows schedule before creation.
Windows Listing Behavior
On Windows, listCrons() reads all scheduled tasks it can map into a usable entry.
- tasks created by this package are restored from JSON metadata stored in the task description
- tasks created outside the package are best-effort mapped from their Task Scheduler trigger definitions
- imported tasks may use descriptive schedule labels such as
At log on of any user,Event trigger, orMultiple triggers definedwhen they cannot be represented as a normal 5-field cron expression
Because imported Windows tasks are included in the listing order, index-based updateCron() and removeCron() operations act on the visible Task Scheduler list. removeAllCrons() remains limited to tasks created by this package.
Supported Human-Readable Expressions
The following human-readable expressions are supported:
every minute→* * * * *every hour→0 * * * *every day→0 0 * * *every week→0 0 * * 0every month→0 0 1 * *every year→0 0 1 1 *every N minutes→*/N * * * *(where N is 1-59)every N hours→0 */N * * *(where N is 1-23)every N days→0 0 */N * *(where N is 1-31)
You can also use standard cron expressions directly, which will be validated and used as-is.
API Reference
CronManager
Methods
__construct(?string $crontabPath = null, ?SchedulerAdapter $schedulerAdapter = null)- Create a new CronManager instancelistCrons(bool $includeHumanReadable = false): array- List all cron jobslistCronsWithHumanReadable(): array- List all cron jobs with human-readable schedulesaddCron($scheduleOrJob, ?string $command = null, ?string $comment = null): bool- Add a new cron jobupdateCron(int $index, $scheduleOrJob, ?string $command = null, ?string $comment = null): bool- Update an existing cron jobremoveCron(int $index): bool- Remove a cron job by indexremoveAllCrons(): bool- Remove all cron jobs
CronJob
Methods
__construct(string $schedule, string $command, ?string $comment = null)- Create a new CronJobgetSchedule(): string- Get the cron schedulegetCommand(): string- Get the command to executegetComment(): ?string- Get the optional commentsetSchedule(string $schedule): void- Set the cron schedulesetCommand(string $command): void- Set the commandsetComment(?string $comment): void- Set the commenttoCrontabLine(): string- Convert to crontab line formatstatic fromCrontabLine(string $line): self- Create from crontab line
CronExpressionParser
Static Methods
static parse(string $expression): string- Parse human-readable expression to cron formatstatic isValidCronExpression(string $expression): bool- Validate cron expressionstatic toHumanReadable(string $cronExpression): string- Convert cron expression to human-readable
Testing
Run the test suite:
composer test
Or using PHPUnit directly:
vendor/bin/phpunit
Important Notes
-
Windows Support: Windows uses a Task Scheduler adapter instead of
crontab. The adapter currently supports the most common minute, hour, day, and week-based schedules. -
Windows Listing Scope: On Windows, listing includes both package-managed tasks and imported scheduled tasks when they can be mapped. Bulk removal still only deletes tasks created by this package.
-
Permissions: The script must have permission to modify the current scheduler backend. On Unix that usually means the current user's
crontab; on Windows it means the current user must be allowed to create and update scheduled tasks. -
Backup: Always backup your crontab before making programmatic changes. You can do this manually with:
crontab -l > crontab_backup.txt -
Index-based Operations: When updating or removing cron jobs, use the index from
listCrons(). The index is 0-based and corresponds to the order returned by the active adapter. -
Namespace: The package uses the
ZPMPackages\CronManagernamespace.
License
MIT
Author
ZPMPackages