robuust/laravel-heroku-queue-listener
Laravel Heroku Queue Listener helps run Laravel queue workers on Heroku. It provides a listener tailored to Heroku worker dynos, making it easier to process background jobs reliably and keep queue processing running smoothly in a Heroku environment.
Since this is the initial v1.0.0, treat every public surface as newly minted: expect a small but real chance of post-release patches, and pin the version in composer.json ("^1.0" is fine for a 1.x, but check the release cadence before using "*" or a floating dev constraint).
Install and inspect the manifest first.
composer require vendor/package:^1.0
Before touching config, open the package's composer.json and look for extra.laravel.providers and extra.laravel.aliases. That tells you exactly what auto-discovery will register and whether you need to wire anything manually (older Laravel versions and dont-discover setups skip this).
Publish and diff the config.
php artisan vendor:publish --provider="Vendor\Package\PackageServiceProvider" --tag=config
Read the published file top to bottom — it's the cheapest documentation that ships with the package and often documents defaults the README skips. Commit it so config changes show up in code review.
Run the migrations (if any) before anything else.
php artisan vendor:publish --tag=package-migrations
php artisan migrate
Inspect the migration file: indexes, foreign keys, and soft-delete columns tell you what the package actually does and how it expects to be queried.
Smoke-test the happy path in tinker.
php artisan tinker
>>> app(\Vendor\Package\SomeService::class)
Resolving from the container before writing feature code surfaces binding issues (wrong service provider order, missing config) in seconds instead of after you've wired it into a controller.
First real use case: wire the package into a single feature — one controller, one job, or one Blade component — and get it running in a local environment with real DB data. Resist integrating across the app before that one path works.
Prefer constructor injection over facades. Laravel auto-discovery makes facades tempting, but constructor-injected contracts (e.g. Vendor\Package\Contracts\Foo) stay testable and keep the package's coupling out of your application code:
public function __construct(private FooContract $foo) {}
Wrap, don't spread. Create a thin adapter in app/Services/ that owns all direct package calls. Two benefits: you can swap implementations later, and you have one place to add logging/telemetry when the vendor's behaviour gets surprising.
Config-driven behaviour, not conditional code in your app. Most Laravel packages expose driver/manager patterns (like Cache, Broadcast, Queue). Where the package offers a manager + drivers, register your driver via the package's documented extend() method rather than if/else branching on config at call sites.
Event and listener integration. If the package dispatches events (look for Illuminate\Contracts\Events\Dispatcher in its constructor), subscribe to them rather than polling state:
Event::listen(Vendor\Package\Events\ThingHappened::class, fn ($e) => /* ... */);
Check whether events are dispatched synchronously — if so, Event::queueable() won't help; you'd need ShouldDispatchAfterCommit on the listener or DB::afterCommit.
Testing setup. Bind the package's contract to a fake in your TestCase::setUp():
$this->app->instance(FooContract::class, new InMemoryFoo());
For integration tests that need the real thing, use RefreshDatabase and call the package's own ::fake() static if it ships one (check src/Testing/). If it doesn't, add a Feature test that exercises one end-to-end path and keep it fast.
Jobs and queues. If the package provides queueable jobs, publish them into app/Jobs/ via the package's --tag=jobs (if present) and wrap them if you need per-tenant or per-connection overrides — otherwise you're locked into the vendor's $this->onQueue() choice.
.env reads inside package config files. After deploying, always php artisan config:cache (and route:cache/view:cache as applicable) and verify your env() calls live in the app's config files, not in the package's. If the package's config uses env() directly, refactor at the adapter layer — do not patch vendor files.AppServiceProvider::register() or in config/app.php if you see "table already exists" / "no such table" in tests.dont-discover bites in CI. If your CI runs composer install --no-dev --prefer-dist, auto-discovery still works; but if you use a custom PackageManifest or a composer.json extra.laravel.dont-discover, the package will be silent. Add a single assertion in a boot test: $this->assertTrue(app()->bound(FooContract::class));1.0.0. Use ^1.0 but keep a composer.lock and read the v1.0.1+ changelog before composer update. The first week after an initial release is the highest-risk window for patch-level surprise.tinker first, then check php artisan about to confirm the provider is registered and booted. Facade errors like "A facade root has not been set" almost always mean the provider didn't load — check bootstrap/providers.php (Laravel 11+) or config/app.php (10 and below).ServiceProvider::extend() calls, Macroable traits, and any Contracts/ directory. Those are your sanctioned overrides. Anything else is vendor-file editing and will be lost on composer update.Facade::clearResolvedInstances() in tearDown() if your tests swap the underlying binding — otherwise a cached instance from a prior test bleeds into the next one.How can I help you explore Laravel packages today?