Weave Code
Code Weaver
Helps Laravel developers discover, compare, and choose open-source packages. See popularity, security, maintainers, and scores at a glance to make better decisions.
Feedback
Share your thoughts, report bugs, or suggest improvements.
Subject
Message

Scheduler Laravel Package

symfony/scheduler

Symfony Scheduler component adds cron-like task scheduling powered by Symfony Messenger. Define recurring or one-off jobs, route them through transports and workers, and run tasks reliably within Symfony apps with first-class framework integration.

View on GitHub
Deep Wiki
Context7

Getting Started

Minimal Steps to First Use

  1. Installation:

    composer require symfony/scheduler
    

    (Note: In Laravel, this is redundant—use native schedule:run instead.)

  2. Define a Scheduled Task (Symfony-style):

    use Symfony\Component\Scheduler\Attribute\AsCronTask;
    
    #[AsCronTask("0 0 * * *", name: "daily_report")]
    public function generateDailyReport(): void
    {
        // Task logic
    }
    

    (Laravel equivalent: Schedule::command('report:generate')->daily();)

  3. Register the Task as a Service:

    # config/services.yaml (Symfony)
    services:
        App\Command\GenerateDailyReportCommand:
            tags: [scheduler.task]
    

    (Laravel: No config needed—use Schedule::command() in app/Console/Kernel.php.)

  4. Run the Scheduler:

    php bin/console scheduler:consume
    

    (Laravel: php artisan schedule:run via cron or schedule:work for testing.)


First Use Case: Replacing a Cron Job

Symfony Scheduler:

#[AsCronTask("*/5 * * * *", name: "sync_data")]
public function syncData(): void
{
    // Sync logic
}

Laravel Equivalent:

protected function schedule(Schedule $schedule): void
{
    $schedule->command('sync:data')->everyFiveMinutes();
}

Key Difference: Symfony requires #[AsCronTask] attributes + Messenger setup, while Laravel uses fluent methods in Kernel.php.


Implementation Patterns

1. Declarative Scheduling

Symfony:

#[AsFrequencyTask("PT1H", name: "hourly_backup")]
public function backupDatabase(): void
{
    // Backup logic
}

Laravel:

$schedule->command('backup:run')->hourly();

Pattern: Use attributes in Symfony; use method chaining in Laravel. Symfony requires explicit scheduler.task tag registration.


2. Dynamic Schedules via ScheduleProviderInterface

Symfony:

use Symfony\Component\Scheduler\ScheduleProviderInterface;

class DynamicScheduleProvider implements ScheduleProviderInterface
{
    public function getSchedules(): iterable
    {
        yield new CronTask(
            '0 0 * * *',
            new Message(new GenerateReportCommand())
        );
    }
}

Laravel Equivalent:

$schedule->call([ReportService::class, 'generate'])->dailyAt('00:00');

Pattern: Symfony’s ScheduleProviderInterface is useful for runtime-generated schedules. Laravel achieves this via closures or dependency injection in Schedule::call().


3. Integrating with Messenger Transports

Symfony:

# config/packages/messenger.yaml
framework:
    messenger:
        transports:
            async: '%env(MESSENGER_TRANSPORT_DSN)%'
        routing:
            'Symfony\Component\Scheduler\Message\ScheduleMessage': async

Laravel:

// config/queue.php
'connections' => [
    'database' => [
        'driver' => 'database',
        'table' => 'jobs',
        'queue' => 'default',
    ],
],

Pattern: Symfony ties scheduling to Messenger transports (e.g., AMQP, Doctrine, Redis). Laravel uses its own queue system—no bridging needed.


4. Handling Task Results and Events

Symfony:

use Symfony\Component\Scheduler\Event\PostRunEvent;

public function onTaskRun(PostRunEvent $event): void
{
    if ($event->isSuccess()) {
        // Log success
    }
}

Laravel:

use Illuminate\Bus\FailedJob;
use Illuminate\Queue\Events\JobProcessed;

Event::listen(JobProcessed::class, function (JobProcessed $event) {
    if (!$event->job->failed()) {
        // Log success
    }
});

Pattern: Symfony’s PostRunEvent mirrors Laravel’s JobProcessed/FailedJob events. Symfony requires manual event listeners; Laravel uses built-in queue events.


5. Skipping Missed Tasks

Symfony:

#[AsCronTask("*/10 * * * *", name: "log_metrics", skipIfMissed: true)]
public function logMetrics(): void
{
    // Metrics logic
}

Laravel:

$schedule->command('metrics:log')->everyTenMinutes()->withoutOverlapping();

Pattern: Symfony’s skipIfMissed is similar to Laravel’s withoutOverlapping(), but Symfony requires attribute configuration.


Gotchas and Tips

Pitfalls

  1. PHP Version Mismatch:

    • Symfony 8.x requires PHP 8.4+, but Laravel 10/11 max at 8.3. Downgrading Symfony risks unsupported features.
    • Laravel Tip: Use native scheduler—no version conflicts.
  2. Duplicate Schedule Names:

    • Symfony throws an error if two tasks share the same name in #[AsCronTask].
    • Debugging: Check scheduler.task service tags in DI container.
    • Laravel Tip: Laravel’s Schedule uses command/job namespaces to avoid collisions.
  3. Messenger Transport Complexity:

    • Symfony’s scheduler:consume requires a running Messenger worker (e.g., php bin/console messenger:consume async).
    • Gotcha: Forgetting to configure transports or routes breaks scheduling.
    • Laravel Tip: Use php artisan queue:work—no extra setup needed.
  4. Attribute vs. Method Chaining:

    • Symfony relies on #[AsCronTask] attributes, which may feel verbose for simple schedules.
    • Tip: Prefer #[AsFrequencyTask] for interval-based tasks (e.g., PT1H for hourly).
    • Laravel Tip: Method chaining (->hourly()) is more concise.
  5. No Native Laravel Integrations:

    • Symfony Scheduler lacks Horizon/Nova/Forge support. Custom adapters are needed for monitoring.
    • Tip: Use Symfony’s scheduler:list command for basic visibility.
    • Laravel Tip: Horizon provides real-time job monitoring out of the box.

Debugging Tips

  1. Check Schedule Registration:

    php bin/console debug:container App\Command\MyTaskCommand
    
    • Verify the scheduler.task tag is present.
    • Laravel: No debug needed—tasks are auto-registered in Kernel.php.
  2. Inspect Missed Tasks:

    • Symfony logs missed tasks to var/log/scheduler.log (if configured).
    • Laravel: Use telescope:record or Horizon’s "Failed Jobs" tab.
  3. Validate Cron Syntax:

    • Use crontab.guru to test Symfony’s cron expressions.
    • Laravel: Use ->cron() with the same syntax.
  4. Handle Argument Passing:

    • Symfony’s #[AsCronTask] may fail if passing arrays as arguments (fixed in v8.0.4).
    • Workaround: Use new Message(new MyCommand($arg1, $arg2)).
    • Laravel: Pass arguments directly: Schedule::command('my:command', ['arg1', 'arg2']).
    • Gotcha: Symfony’s #[AsCronTask] with arguments requires new Message() wrapping.

Extension Points

  1. Custom Schedule Providers:

    • Implement ScheduleProviderInterface to dynamically generate schedules at runtime.
    • Use Case: Tenant-specific schedules or feature-flagged tasks.
    • Laravel: Achieve this with closures in Schedule::call() or middleware.
  2. Event Listeners:

    • Extend PostRunEvent to react to task outcomes (e.g., send Slack alerts).
    • Symfony Example:
      public static function getSubscribedEvents(): array
      {
          return [
              PostRunEvent::class => 'onTaskRun',
          ];
      }
      
    • Laravel: Use JobProcessed/FailedJob events.
  3. Transport Adapters:

    • Symfony supports custom transports (e.g., Kafka). Laravel’s queue system is more limited but sufficient for most use cases.
    • Tip: Avoid custom transports unless you need Symfony’s advanced features.
  4. Testing:

    • Symfony provides SchedulerTestCase for testing schedules.
    • Laravel: Use Schedule::fake() in PHPUnit:
      use Illuminate\Support\Facades\Schedule;
      
      public function test_scheduled_task()
      {
          Schedule::fake();
          $this->artisan('schedule:run');
          Schedule::assertRan('command:test');
      }
      
Weaver

How can I help you explore Laravel packages today?

Conversation history is not saved when not logged in.
Prompt
Add packages to context
No packages found.
davejamesmiller/laravel-breadcrumbs
artisanry/parsedown
christhompsontldr/phpsdk
enqueue/dsn
bunny/bunny
enqueue/test
enqueue/null
enqueue/amqp-tools
milesj/emojibase
bower-asset/punycode
bower-asset/inputmask
bower-asset/jquery
bower-asset/yii2-pjax
laravel/nova
spatie/laravel-mailcoach
spatie/laravel-superseeder
laravel/liferaft
nst/json-test-suite
danielmiessler/sec-lists
jackalope/jackalope-transport