code7day/lighthouse-passport
Integrates Laravel Passport with Lighthouse GraphQL, letting you guard queries and mutations using Passport-issued OAuth2 tokens. Adds auth directives and middleware so your GraphQL API can authenticate users and clients without extra boilerplate.
v1.0 is the package's first tagged release, so there is no migration path, no deprecation surface, and no historical behaviour to compare against — treat it as a greenfield dependency rather than an upgrade.
Install and pin
composer require vendor/package:^1.0
Pin to ^1.0 rather than dev-main. With a single initial tag there is no proven stability record, and ^1.0 gives you a clean floor for the first patch releases without letting the constraint float backwards to pre-release commits.
Where to look first, in this order
composer.json → extra.laravel.providers and extra.laravel.aliases. Confirms whether the service provider is auto-discovered (Laravel 5.5+) or needs manual registration in config/app.php.
The package's config/ directory. If it ships a config file, publish it before writing any code:
php artisan vendor:publish --provider="Vendor\Package\PackageServiceProvider"
The service provider's register() and boot() methods. This is the fastest way to see what is bound into the container, whether anything is deferred, and which singletons will persist across a request.
The package README's quickstart, read after the provider — the README often omits bindings that matter for your use case.
First use case
Resolve the package's primary entry point from the container rather than instantiating it directly, so you inherit whatever configuration and dependencies the provider wires up:
use Vendor\Package\Package;
public function __construct(private Package $package) {}
Then exercise it in a single, isolated place — a Tinker session (php artisan tinker) or one test — before wiring it into application code. On a .0 release this is where you validate that the documented happy path actually matches the shipped API.
Constructor injection over facades
Prefer injecting the package's concrete class or interface into controllers, jobs, and actions. Facades are convenient but they resolve from the container at call time, which makes it harder to swap in a fake during testing and hides the dependency from static analysis. Use the facade only in Blade, Artisan commands, and quick scripts.
Wrap it behind your own boundary
Because this is v1.0, keep the package's classes out of your domain layer. Define a small interface in your app (ReportGenerator, PaymentGateway, whatever the package does), implement it with a thin adapter that calls the package, and bind it in a service provider:
$this->app->bind(ReportGenerator::class, PackageReportGenerator::class);
If v2 introduces breaking changes — statistically likely for a first release — you rewrite the adapter, not every call site. This is cheap insurance and costs maybe twenty minutes.
Queue long-running work
If the package performs HTTP calls, file processing, or anything network-bound, do not call it synchronously in a request cycle. Inject it into a job and dispatch:
dispatch(new GenerateReport($payload));
Watch for the package holding non-serialisable state (clients, connections) on the injected instance — that pattern is fine in a job that resolves fresh per dispatch, but will break if you inject a singleton into a queued payload.
Test against a fake, not the network
In TestCase or your feature tests, bind a fake implementation of your adapter interface, or use the package's own testing helpers if it ships them. Keep one narrow integration test that hits the real thing, tagged @group integration and excluded from the default suite.
Configuration over code
Anything the package exposes in config/package.php should be read via config() and set per-environment in .env. Resist editing the published config file inline with application-specific logic — it becomes untrackable the moment the package ships a new default.
Config caching silently drops late-bound config
If you read config inside a closure in boot() or at runtime in a way that depends on values set after the provider boots, php artisan config:cache will freeze the wrong values. Always run php artisan config:clear after changing .env locally and after any package config publish.
Auto-discovery is easy to break
The provider is only auto-discovered when it appears in your composer.json's installed packages with the extra.laravel block intact. If you fork or path-repository the package, you must re-register the provider manually — the symptom is a "Target class does not exist" or an unbound interface at resolution time.
Singletons leak state across requests
Check whether register() uses singleton() or bind(). Singletons survive for the life of the application instance, which in Octane or a long-running worker means state from request one is visible in request two. If the package resolves as a singleton and holds mutable state, add a reset in a Octane::tick() listener or force bind() in your own provider.
No upgrade guide yet
There is nothing to read for v1.0 → v1.1 behaviour changes. Before bumping, diff the package's CHANGELOG.md and its service provider; a change to constructor signatures or config keys will surface as a container resolution error rather than a clear deprecation notice. Read the diff, don't trust the version number.
Debugging resolution failures
When you get Unresolvable dependency resolving [Parameter #0 ...], the package is usually asking for an interface nobody bound. Confirm the provider actually ran:
php artisan about
and check bootstrap/cache/packages.php after a composer dump-autoload. That file is the manifest of discovered providers, and it is stale more often than you'd expect.
Extension points
Look for Manager classes or extend() methods before you subclass anything. Laravel packages commonly expose a driver pattern (Package::extend('custom', fn () => ...)) or publishable contracts. Registering a custom driver in your own AppServiceProvider::boot() is the supported route and survives package upgrades; subclassing internals does not.
Version pinning for production
Set composer.lock and commit it. On a first release, treat patch bumps as reviewable changes rather than automatic — run composer update vendor/package --dry-run to see what a bump would pull in before letting CI do it silently.
How can I help you explore Laravel packages today?