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

Laravel Artisan Dispatchable Laravel Package

spatie/laravel-artisan-dispatchable

Register Laravel jobs as Artisan commands by implementing the ArtisanDispatchable interface. Dispatch queued jobs via CLI (e.g., php artisan process-podcast) so long-running tasks won’t block the scheduler, while remaining runnable from Artisan.

View on GitHub
Deep Wiki
Context7

Getting Started

Minimal Setup

  1. Installation:

    composer require spatie/laravel-artisan-dispatchable
    

    Publish the config (optional):

    php artisan vendor:publish --provider="Spatie\ArtisanDispatchable\ArtisanDispatchableServiceProvider"
    
  2. Mark a Job as Artisan-Dispatchable: Implement the ArtisanDispatchable interface in your job class:

    use Spatie\ArtisanDispatchable\Jobs\ArtisanDispatchable;
    
    class ProcessPodcast implements ShouldQueue, ArtisanDispatchable
    {
        public function handle() { /* ... */ }
    }
    
  3. First Use Case: Run the job directly via Artisan:

    php artisan process-podcast
    

    The job will execute asynchronously (if queued) or synchronously (if not queued).


Where to Look First

  • Job Naming: The Artisan command name is derived from the job class name (e.g., ProcessPodcastprocess-podcast).
  • Config File: Check config/artisan-dispatchable.php for customizations (e.g., command naming conventions, middleware).
  • Testing: Use php artisan to test jobs locally before scheduling them.

Implementation Patterns

Core Workflow

  1. Define the Job:

    class SendWelcomeEmail implements ShouldQueue, ArtisanDispatchable
    {
        public function handle() {
            Mail::to($user)->send(new WelcomeEmail($user));
        }
    }
    
    • The job is now both queueable and Artisan-dispatchable.
  2. Dispatch via Artisan:

    php artisan send-welcome-email --user=123
    
    • Pass arguments via CLI flags (e.g., --user=123 or --queue=high).
  3. Schedule via Laravel Scheduler:

    // app/Console/Kernel.php
    protected function schedule(Schedule $schedule) {
        $schedule->job(new SendWelcomeEmail($user))
                 ->everyMinute();
    }
    
    • The job runs asynchronously, avoiding scheduler delays.

Integration Tips

  1. Passing Arguments:

    • Use constructor injection or static methods to accept CLI arguments:
      class ProcessPodcast implements ArtisanDispatchable {
          public function __construct(public int $podcastId) {}
      
          public static function command() {
              return 'process-podcast';
          }
      }
      
      Run with:
      php artisan process-podcast --podcastId=42
      
  2. Queue Configuration:

    • Override the queue connection dynamically:
      public function handle() {
          Queue::connection('high')->push($this);
      }
      
    • Pass via CLI:
      php artisan process-podcast --queue=high
      
  3. Middleware:

    • Apply middleware to Artisan-dispatchable jobs:
      class ProcessPodcast implements ArtisanDispatchable {
          public function handle() {
              // Middleware runs here
          }
      }
      
    • Register middleware in ArtisanDispatchableServiceProvider.
  4. Batching:

    • Dispatch multiple jobs in bulk:
      php artisan process-podcast --batch --ids=1,2,3
      
    • Implement handleBatch() in your job:
      public function handleBatch(array $podcastIds) { /* ... */ }
      
  5. Event Listeners:

    • Trigger events before/after job execution:
      class ProcessPodcast implements ArtisanDispatchable {
          public function handle() {
              event(new JobStarted($this));
              // Work...
              event(new JobFinished($this));
          }
      }
      

Gotchas and Tips

Pitfalls

  1. Command Naming Conflicts:

    • Avoid naming jobs that clash with existing Artisan commands (e.g., MakeModel).
    • Customize naming via command() method or config:
      public static function command() {
          return 'custom-process-podcast';
      }
      
  2. Argument Parsing:

    • CLI arguments are parsed as strings. Cast manually in handle():
      public function handle() {
          $this->podcastId = (int) $this->podcastId;
      }
      
    • Use --json flag for complex data:
      php artisan process-podcast --data='{"key":"value"}'
      
  3. Queue vs. Sync Execution:

    • If the job doesn’t implement ShouldQueue, it runs synchronously during Artisan execution.
    • Add ShouldQueue to force async behavior:
      class ProcessPodcast implements ShouldQueue, ArtisanDispatchable { /* ... */ }
      
  4. Dependency Injection:

    • Avoid injecting services directly into the job constructor if they’re not serializable.
    • Use resolve() or lazy-load dependencies in handle().
  5. Error Handling:

    • Artisan commands exit with status 0 even if the job fails (unless thrown as an exception).
    • Log failures explicitly:
      try {
          $this->handle();
      } catch (\Throwable $e) {
          \Log::error("Job failed: {$e->getMessage()}");
          throw $e; // Re-throw to mark Artisan command as failed
      }
      

Debugging Tips

  1. Check Job Execution:

    • Use php artisan queue:work --once to debug jobs manually.
    • Tail logs:
      tail -f storage/logs/laravel.log
      
  2. Inspect Arguments:

    • Dump CLI input in handle():
      public function handle() {
          \Log::debug('Input:', $this->input());
      }
      
  3. Artisan Command Help:

    • Generate help text for your job:
      public static function signature() {
          return 'process-podcast {--user= : User ID} {--queue= : Queue name}';
      }
      public static function description() {
          return 'Processes a podcast for a given user';
      }
      
    • View help:
      php artisan process-podcast --help
      

Extension Points

  1. Custom Command Logic:

    • Override ArtisanDispatchableServiceProvider to add pre/post hooks:
      public function boot() {
          Artisan::resolving(function ($command) {
              if ($command instanceof ArtisanDispatchableCommand) {
                  // Pre-execution logic
              }
          });
      }
      
  2. Dynamic Job Resolution:

    • Register dynamic jobs via service provider:
      $this->app->bind('command:custom-job', function () {
          return new CustomJob();
      });
      
  3. Testing:

    • Mock jobs in tests:
      $job = new ProcessPodcast();
      $this->artisan('process-podcast')
           ->expectsQuestion('Confirm?', 'yes')
           ->assertExitCode(0);
      
  4. Laravel 10+ Compatibility:

    • Ensure ShouldQueue is imported from Illuminate\Contracts\Queue\ShouldQueue (not Illuminate\Bus\Queueable).
    • Use Illuminate\Bus\Queueable for additional features like onQueue() or delay().
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