survos/pixie-bundle
A Symfony bundle that integrates the Pixie lightweight PHP query builder, offering service configuration, dependency injection, and convenient database access for Symfony applications.
Pin to the tagged release rather than tracking the branch. As of 1.5.600 the package is consumed as a versioned dependency, so the dev-main constraint that earlier setup guides used is no longer the supported path:
composer require vendor/package:^1.5
If you already have it installed from dev-main, rewrite the constraint in composer.json and refresh the lock file so the resolved commit is anchored to a tag:
composer require vendor/package:^1.5 --update-with-dependencies
composer show vendor/package # confirm the installed version is a tag, not dev-main
First things to look at, in order:
composer show -a vendor/package — confirm the tagged version and its declared Laravel/framework constraints before committing to the upgrade.config/ after publishing (php artisan vendor:publish --provider="Vendor\Package\ServiceProvider"). This is the surface you will actually touch day to day.First use case: resolve the package's primary entry point from the container rather than instantiating it, and confirm it boots cleanly in a fresh environment before layering it into existing code:
$service = app(\Vendor\Package\Contracts\Service::class);
$result = $service->handle($payload);
If that returns without a binding exception and the config file exists, the integration is sound and you can move on to the real workflows.
Constructor injection over facades. Bind the package's contract in your own service classes. This keeps your code testable and means a future major version can swap implementations without touching call sites. Reserve the facade for one-off usage in controllers and Blade.
Wrap it, don't scatter it. Create a thin application-level adapter around the package so its types do not leak into your domain layer. When the package changes signatures, you edit one class instead of grepping the codebase:
final class Notifier
{
public function __construct(private \Vendor\Package\Contracts\Service $service) {}
public function send(Notification $notification): void
{
$this->service->handle($notification->toPayload());
}
}
Publish config in every environment, commit it once. Publish into config/ and drive environment differences through .env values read by that file, not through conditionals in application code. Ship the published file to staging and production identically.
Queue anything that touches the network. If the package performs outbound calls or heavy processing, dispatch through a job and let the package run inside the worker. This isolates failures from the request cycle and makes retries a matter of job configuration rather than bespoke error handling.
Test against the contract, not the package. In your test suite, bind a fake implementation of the contract in a service provider override. Only write integration tests that hit the real package for the handful of behaviours where its exact output matters.
Register package events selectively. If the package emits events, listen only to the ones you need and keep listeners queued. Package events firing synchronously in a request can quietly add latency as your listener count grows.
Version discipline. With tagged releases now the norm, treat each bump as reviewable: read the changelog, run the suite, and use composer outdated in CI to surface drift before it surprises you on deploy day.
dev-main will silently reappear. A stale composer.lock, a copied snippet from an older guide, or a transitive constraint can reintroduce the branch requirement. Guard against it in CI:
composer show vendor/package --format=json | grep -q '"version": "dev-main"' && exit 1 || exit 0
Or simply assert the installed version matches ^1.5 in a build step.
Minimum-stability traps. Requiring a branch often forced "minimum-stability": "dev" in composer.json. After moving to a tag, remove that or you will start pulling unstable versions of unrelated dependencies without noticing.
Config cache hides published changes. After publishing or editing the package config, run php artisan config:cache in environments that cache. config:clear is the first thing to try when configuration appears ignored.
Migration ordering. Package migrations can collide with your own table names or run in an unexpected order relative to app migrations. Publish them (--tag=migrations) if you need to control ordering, and never edit a package migration after it has run in production.
Auto-discovery is not guaranteed. Some packages disable it or require a manual provider entry in bootstrap/providers.php (Laravel 11+) / config/app.php (older). A missing binding exception is usually this, not a code error.
Debugging the integration. Use php artisan tinker to resolve the contract and inspect the resolved instance; app()->getBindings() confirms what is registered. For runtime failures, wrap the call in a try/catch that logs the payload alongside the exception — package exceptions frequently omit the input that caused them.
Extension points to prefer. Contracts and events are stable surfaces. Extending concrete classes or overriding protected methods is not; if you find yourself subclassing, that behaviour belongs in your adapter.
Upgrade checklist for point releases like 1.5.600. Re-read the changelog, diff the published config against yours (php artisan vendor:publish --force into a scratch directory), run the full suite plus a queue worker smoke test, then deploy config-cache-last so a bad config does not take down the app on boot.
How can I help you explore Laravel packages today?