fragkp/laravel-route-breadcrumb
Generate breadcrumbs automatically from your Laravel route names—no manual configuration or blade templates required. This lightweight package builds clean, customizable trails straight from your routes, helping users navigate your app while keeping breadcrumb logic centralized and easy to maintain.
This is a major release (4.0.0) whose only documented change is a narrowed platform support matrix: Laravel 8.x and PHP 7.4 / 8.x. Treat the release notes as an incomplete changelog and read the package's UPGRADE.md/CHANGELOG.md and diff before you assume behavior is unchanged.
Three checks before you write any code:
php -v must report 7.4 or 8.x, and composer show laravel/framework must report an 8.x line. If you are on Laravel 9/10 or PHP 8.2, do not install 4.0.0 — pin the previous major (composer require vendor/package:^3.0) and plan the upgrade around the package, not the framework.composer.json. The notes say "PHP 7.4|8.x only," which is unusually loose. Look at the actual require block to see whether it is ^7.4|^8.0 (which may or may not exclude 8.2/8.3) or a hard >=7.4 <8.2. This determines whether a routine composer update can silently land you on an unsupported runtime.extra.laravel.providers is standard on 8.x, but a major bump is a common moment for a provider to be renamed or split. If the provider name changed, an existing config/app.php entry (or a cached bootstrap/cache/packages.php) will point at a class that no longer exists.First use case: install, publish, and exercise the smallest end-to-end path — one config publish, one facade or injected-service call, one assertion in a feature test — before touching existing call sites. That establishes a working baseline against which the rest of the migration diff is meaningful.
composer require vendor/package:^4.0
php artisan vendor:publish --provider="Vendor\Package\PackageServiceProvider"
php artisan config:clear && php artisan package:discover
Upgrade-in-place with a pinned baseline. On a Laravel 8 app already using v3, upgrade in a dedicated branch and let Composer tell you what the new constraints reject:
composer why-not vendor/package 4.0.0
composer update vendor/package --with-dependencies -W
why-not is the fastest way to discover that another dependency (an auth or admin package, a dev tool) still requires the old major. Resolve that conflict deliberately rather than with --ignore-platform-reqs.
Isolate the package behind one seam. Whatever the package does — payments, search, media, permissions — wrap it in a thin application-level service or interface and inject that, rather than calling the facade from controllers and jobs. A 4.0.0 that changed nothing but the support matrix is a signal the maintainer is doing housekeeping; the next major may not be so quiet, and a single seam turns the next upgrade into a one-file change.
// app/Services/Billing.php
final class Billing
{
public function __construct(private \Vendor\Package\Client $client) {}
public function charge(Order $order): Receipt
{
return $this->client->charge($order->total, $order->currency);
}
}
Config as the integration contract. Publish the config file and commit it. Read values through config('package.key'), never by instantiating the package's internals directly. On a major bump, re-publish to a temp path and diff against yours — removed or renamed keys are the most common silent breakage, and they fail at runtime, not at install time.
php artisan vendor:publish --provider="Vendor\Package\PackageServiceProvider" --force --tag=config
git diff config/package.php
Queue and event boundaries. If the package dispatches events or ships jobs, register listeners in a dedicated EventServiceProvider block rather than inline closures, and make queued jobs idempotent. Major releases frequently change event payload shapes or job constructor signatures; a queued job serialized under v3 and processed after deploy under v4 will fail on unserialize. Drain the queue before deploying, or version the job class name.
Test against the real contract, not the facade. Use the package's own fakes or a fake of your wrapper interface in unit tests, and keep a small number of integration tests that hit the real package (with RefreshDatabase and a sandbox credential). This keeps the suite fast while still catching the breakage a major bump actually introduces.
Runtime pinning in CI. Add a matrix entry or a guard step so CI fails loudly on an unsupported combination:
- run: composer check-platform-reqs
This catches a developer on PHP 8.2 installing a tree Composer's platform config would otherwise allow.
^8.0, PHP 8.2/8.3 may satisfy Composer while the package's own code is untested there (dynamic properties, ${var} string interpolation, and utf8_encode deprecations are the usual offenders). Set config.platform.php in composer.json to your production runtime so local installs cannot drift from the server.php artisan config:clear, route:clear, view:clear, and deleting bootstrap/cache/*.php resolves a large share of "provider not found" and "class does not exist" reports post-major. In production, run config:cache and route:cache as part of the deploy, not before it.A facade root has not been set almost always means the service provider is not registered — check bootstrap/cache/packages.php was regenerated (composer dump-autoload && php artisan package:discover).git log --oneline v3..v4 on the repo is usually more informative than the release notes.phpstan.neon → phpVersion: 70400) so violations surface in CI.$app->bind(...) in a service provider) over editing published files, so a future major can be dropped in without re-applying patches. Never edit vendor/.^4.0 in composer.json and commit composer.lock. A floating * or dev-master on a package that just made a breaking major is how unreviewed upgrades reach production.How can I help you explore Laravel packages today?