carles/scheduled-command-bundle
Installation
composer require carles/scheduled-command-bundle
Ensure your server has the Unix at command installed (sudo apt-get install at on Debian/Ubuntu).
Enable the Bundle
Add to config/bundles.php:
return [
// ...
Carles\ScheduledCommandBundle\CarlesScheduledCommandBundle::class => ['all' => true],
];
Configure the Bundle
Update config/packages/scheduled_command.yaml (or create it):
scheduled_command:
temp_command_files_dir: '%kernel.project_dir%/var/scheduled_commands'
First Use Case Schedule a simple command via a controller or CLI:
use Carles\ScheduledCommandBundle\Entity\ScheduledCommand;
$scheduledCommand = new ScheduledCommand();
$scheduledCommand->setCommand('php /path/to/your/console-command');
$scheduledCommand->setDatetime(new \DateTime('+1 day')); // Run once in 24 hours
$entityManager = $this->getDoctrine()->getManager();
$entityManager->persist($scheduledCommand);
$entityManager->flush();
One-Time Commands
Use setDatetime() to schedule a command for a specific future time:
$scheduledCommand->setDatetime(new \DateTime('2024-12-31 23:59:59'));
Recurring Commands
Combine with a cron-like approach by creating multiple ScheduledCommand entities (no built-in recurrence, but you can automate this with a separate job).
Dynamic Command Generation Generate commands dynamically (e.g., passing arguments):
$scheduledCommand->setCommand(
'php artisan your:command --user={$userId} --force'
);
Integration with Symfony Console Schedule Symfony console commands directly:
$scheduledCommand->setCommand('php bin/console app:send-emails');
prePersist and preUpdate events to trigger the at command. Ensure your ScheduledCommand entity is properly mapped.at command failures gracefully.$this->logger->info('Scheduled command', [
'command' => $scheduledCommand->getCommand(),
'datetime' => $scheduledCommand->getDatetime()->format('Y-m-d H:i:s'),
]);
Unix Dependency
schtasks or third-party libraries.at is installed with which at in your terminal.File Permissions
temp_command_files_dir must be writable by the web server user (e.g., www-data or nginx)./tmp may not be ideal; specify a custom directory in config:
scheduled_command:
temp_command_files_dir: '%kernel.project_dir%/var/scheduled_commands'
Command Length Limits
at command has a 1024-character limit for arguments. Split long commands or use environment variables:
$scheduledCommand->setCommand('php script.php --env=' . getenv('APP_ENV'));
Timezone Issues
setDatetime() uses a timezone-aware DateTime object:
$dateTime = new \DateTime('+1 hour', new \DateTimeZone('UTC'));
$scheduledCommand->setDatetime($dateTime);
Debugging Scheduled Jobs
at job was created by listing pending jobs:
at -l
temp_command_files_dir.Cleanup Old Commands Add a cron job to remove old command files (e.g., older than 30 days):
find /path/to/scheduled_commands -type f -mtime +30 -delete
Extend the Entity
Add custom fields to ScheduledCommand (e.g., userId, status) and update the bundle’s Doctrine mapping:
// src/Entity/ScheduledCommand.php
/**
* @ORM\Column(type="string", length=255, nullable=true)
*/
private $userId;
Override the Command Writer
Extend the bundle’s CommandWriter service to customize how commands are written to files:
# config/services.yaml
Carles\ScheduledCommandBundle\CommandWriter:
arguments:
$tempDir: '%kernel.project_dir%/var/custom_commands'
$filePrefix: 'custom_'
Testing
Mock the at command in tests using a library like php-at or override the bundle’s AtCommandExecutor service:
$this->container->set('carles_scheduled_command.at_command_executor', $mockExecutor);
Security
$safeCommand = escapeshellarg($userInput);
$scheduledCommand->setCommand($safeCommand);
How can I help you explore Laravel packages today?