Weave 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

Dispatcher Laravel Package

indatus/dispatcher

Indatus Dispatcher is a Laravel package for scheduling Artisan commands and queued jobs with a fluent API. Define cron-style schedules, manage overlaps, and log or email command output, offering a flexible alternative to Laravel's built-in scheduler.

View on GitHub
Deep Wiki
Context7

Getting Started

Install the package and wire it into the framework:

composer require indatus/dispatcher:~1.0

Laravel 4 — add to app/config/app.php:

'Indatus\Dispatcher\ServiceProvider',
'Dispatcher' => 'Indatus\Dispatcher\Facades\Dispatcher',

Laravel 5 — add to config/app.php the same provider and alias, then publish and run:

php artisan config:publish indatus/dispatcher   # L4
php artisan vendor:publish --provider="Indatus\Dispatcher\ServiceProvider"
php artisan migrate --package=indatus/dispatcher  # or --path for published migrations

The one thing that makes Dispatcher "work" is a single crontab entry, because the package evaluates schedules but does not tick itself:

* * * * * php /var/www/myapp/artisan scheduled:run >> /dev/null 2>&1

First use case: scaffold a scheduled command and confirm it is registered.

php artisan scheduled:make BackupDatabase
php artisan scheduled:list
php artisan scheduled:run          # run once manually to verify evaluation

scheduled:make drops a class into app/Console/Scheduled/ (path configurable in config/dispatcher.php). That directory is the primary place to look first — everything else (cron, DB registry, drivers) exists to serve the classes living there.

Implementation Patterns

Fluent schedule definition inside a command class. Each scheduled class extends the package's base and returns a Schedulable:

use Indatus\Dispatcher\Scheduling\ScheduledCommand;
use Indatus\Dispatcher\Scheduling\Schedulable;

class BackupDatabase extends ScheduledCommand
{
    protected $name = 'db:backup';
    protected $description = 'Nightly database dump';

    public function schedule(Schedulable $scheduler)
    {
        return $scheduler
            ->daily()
            ->at(2, 30)
            ->args(['--compress'])
            ->runInBackground();
    }
}

The fluent vocabulary mirrors cron semantics — hourly(), daily(), weekly(), monthly(), at($hour, $minute), and raw cron('*/15 * * * *') when the helpers don't express what you need. Prefer cron() for anything non-obvious (business-hours-only, "every 5 minutes but not at :00") rather than nesting helpers.

Ad-hoc scheduling from a service provider. For one-off invocations that don't deserve a class, register the artisan command directly:

Dispatcher::schedule('cache:warm')
    ->daily()
    ->at(5, 0);

This is the fastest path when migrating an existing crontab line-by-line: one provider method, one Dispatcher::schedule() call per line, and you can delete the crontab entries as you go.

Two drivers, one mental model. config/dispatcher.php selects local or remote. Local runs commands in-process on the web/app host; remote shells out over SSH to another box. The remote driver is the reason teams picked this over raw cron: you can keep all schedule logic in version control on the app server while the actual command executes on a database or worker host. Treat the remote config block as production-critical and diff it per environment.

Background vs foreground. runInBackground() is what you want for anything longer than a few seconds, otherwise scheduled:run (ticking every minute) blocks and subsequent due commands slip. Reserve foreground execution for quick, deterministic commands where you actually want the output captured.

Overlap protection. Long-running jobs need a guard so a slow run doesn't stack on the next tick. Use the package's mutex/locking facility (backed by the published migration) or wrap the inner command in your own lock. This is not optional for anything touching backups, billing, or external APIs with rate limits.

Environment scoping. Wrap registration in an environment check in the provider (if (App::environment('production'))) rather than relying on the schedule itself. It reads better and keeps dev machines from firing production side-effects when someone runs scheduled:run locally.

Gotchas and Tips

  • scheduled:run is not a daemon. It is a one-shot evaluator designed to be invoked every minute by cron. If you run it in a while true loop you will get drift and duplicate launches.
  • Use the absolute php binary in cron. The classic failure is php: command not found under cron's minimal PATH. Use /usr/bin/php or your PHP-FPM's binary explicitly.
  • Laravel 5.1+ has a built-in scheduler. This package predates it and overlaps almost entirely. For any new application, use $schedule->command() in app/Console/Kernel.php. Keep Dispatcher only for legacy Laravel 4.x / early 5.x apps where rewriting the schedule is not worth the risk.
  • The package is effectively unmaintained (last release March 2015). Pin the version in composer.json, and expect to patch it yourself if a PHP or framework upgrade breaks reflection or the SSH driver.
  • Stale database registrations. scheduled:list reads from the package's table, not from disk. Rename or delete a scheduled class without running scheduled:remove and you get phantom entries that error every minute in the logs. After any refactor, run scheduled:list and prune.
  • Config caching will bite you. In Laravel 5, php artisan config:cache snapshots dispatcher.php. Changing the driver or remote host requires a re-cache — otherwise you'll swear the config change "didn't apply."
  • Silent failures by default. Cron redirects to /dev/null, so a failing command produces nothing. Always send output somewhere (>> /var/log/dispatcher.log 2>&1) and have the underlying command log its own start/finish/exit code. Debugging a schedule that "didn't run" without logs is guesswork.
  • Timezone is the app's timezone, not the server's. If config/app.php says UTC but you're reasoning in local time, ->at(2, 30) fires at the wrong hour. Verify with scheduled:list which surfaces the resolved next-run time.
  • Overlap + background is a footgun. runInBackground() gives you parallelism you probably don't want for the same command. Pair it with the mutex, or your nightly job will eventually collide with itself after a slow run.
  • Extension point worth knowing: the scheduling classes are plain PHP returning a Schedulable. If you need custom logic (e.g. "only on the first business day"), subclass or compose around the scheduler rather than fighting the fluent API — that's the seam the package expects you to use.
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.
novasa/laravel-language-center
opencage/geocode
adolfoholzer/parameters
livenetworks/ln-starter
shitoudev/permissionmanager
johannesclimacus/laravel-tui
hocvt/seotools
vitalybaev/sypexgeo
amphibee/themosis-ignition
gito-me/fast-excel
frankyso/laravel-ipaymu
geolize-studio/laravel-chile
boomerangui/chat
cgv/localized-resource
noith/settings
kda/laravel-package
kda/filament-dynamic-navigation
bypersoft/signbox
pairus/product-data
fayne/laravel-filament-cms-core