1. Pin the new version. The 1.2.0 release is a platform-support release (Laravel 10 + PHP 8.1), so the first thing to do is bump the constraint rather than float it:
composer require your-vendor/package:^1.2 --with-all-dependencies
Use --with-all-dependencies (-W) here. A plain composer update your-vendor/package will not move illuminate/support forward on its own, and you can easily end up on 1.1.x with Laravel 9 transitive deps still locked.
2. Confirm you actually got it. Verify both the package version and the resolved framework version:
composer show your-vendor/package
composer why-not your-vendor/package 1.2
why-not is the fastest way to find which other dependency is still holding you below the new constraint.
3. Clear the discovery cache. Packages registered via extra.laravel.providers are cached in bootstrap/cache/packages.php. After the upgrade run:
php artisan package:discover --ansi
php artisan config:clear
The --ansi flag matters: if the service provider fails to boot on the new Laravel version, you get a colored stack trace instead of a silent failure swallowed by the cache file.
4. Look here first. Check the package's composer.json for the exact constraints it now declares:
"require": {
"php": "^8.1",
"illuminate/support": "^9.0|^10.0"
}
Two things to read off this:
^9.0|^10.0 is present, 1.2.0 is a drop-in for Laravel 9 apps and you can upgrade without touching app code.^10.0 only, then 1.2.0 is effectively a new major for anyone on L9, and your upgrade path is coupled to the Laravel 9→10 jump.5. First use case. The realistic day-one scenario is: you are on Laravel 9, you want Laravel 10, and this package was the blocker. The whole job is composer why-not → bump → composer update -W → re-run the test suite. Treat 1.2.0 as a dependency unblock, not a feature release — the notes mention no new API surface, so do not go looking for one.
Upgrade a Laravel 9 app in one pass.
# 1. See what's holding you back
composer why-not your-vendor/package 1.2
# 2. Upgrade the framework and the package together
composer require laravel/framework:^10.0 your-vendor/package:^1.2 -W
# 3. Re-discover and smoke test
php artisan package:discover --ansi
php artisan test
Do the framework bump and the package bump in a single composer transaction. Splitting them leaves you with a transient state where Laravel is 10 but the package still constrains illuminate/support to ^9.0, and Composer will either refuse or silently downgrade the framework back.
Branch-your-constraints pattern. If you maintain multiple apps on different Laravel versions, express the constraint so both work:
"your-vendor/package": "^1.2"
and let the package's own ^9.0|^10.0 do the work. Avoid pinning 1.2.0 exactly in application composer.json — you lose patch fixes and gain nothing, since 1.2.0 introduces no app-visible behaviour.
CI matrix for PHP 8.1. Since 1.2.0 is the first release claiming PHP 8.1, make that explicit in your pipeline rather than inheriting it from the framework:
strategy:
matrix:
php: ['8.1', '8.2']
laravel: ['9.*', '10.*']
exclude:
- php: '8.1'
laravel: '9.*' # only if you've dropped L9
Run the package's own test suite under the new combination before shipping, even if you trust the release notes — "supports PHP 8.1" frequently means "no longer fatals", not "deprecation-clean".
Wrap the package behind your own boundary. This release is a good reminder to have a thin application-level wrapper (a repository, a service class, or a facade alias you control) around package calls. When the next compatibility release lands, you change one file instead of grepping the codebase for use YourVendor\Package\.... If you already have one, this upgrade should require zero changes inside it.
Integration checkpoint after upgrade. Whatever the package's surface is — migrations, a config file, a scheduled job, a queue worker — exercise each entry point once post-upgrade:
php artisan migrate --pretend # if it ships migrations
php artisan vendor:publish --tag=package-config --force # if you've customised config
php artisan queue:work --once # if it dispatches jobs
Laravel 10's schema builder handles column modification natively without doctrine/dbal, so if the package ships migrations that call ->change(), re-test them on a scratch database.
composer update alone will not get you there. The most common failure mode after a release like this is believing you upgraded. composer update your-vendor/package respects existing lock entries for transitive deps; without -W you stay on the old illuminate/*. Always confirm with composer show.
PHP 8.1 deprecation noise. 8.1 promotes "implicitly nullable parameter" and "return type will change" style deprecations. If the package implements ArrayAccess, Iterator, or Countable without return types, you will start seeing Deprecated: lines in logs where Laravel 9 + PHP 8.0 was silent. These are not errors, but they will pollute logs and can fail a strict test suite. Check with:
php -d error_reporting=E_ALL artisan test 2>&1 | grep -i deprecated
If deprecations appear, decide deliberately: silence via error_reporting in non-production, or report upstream — do not let them accumulate.
Dynamic properties. PHP 8.1 is not 8.2, so #[AllowDynamicProperties] is not yet mandatory, but if the package creates stdClass or __get-based DTOs, note it now. This is the release where you want to grep for dynamic property creation so that a future PHP 8.2 release is not a surprise.
Do not assume Laravel 10 app-code migration is free. 1.2.0 makes the package compatible, not your application. Laravel 10 removed several long-deprecated methods and changed change() migration behaviour. Budget for a framework upgrade review in parallel — the package bump is a prerequisite, not the whole task.
Check the constraint direction before you file bugs. If you hit an error after upgrading and composer show reports the package at 1.2.0 but laravel/framework at 9.x, you are in an untested combination only if the constraint is ^10.0. Read composer.json first; it saves a misleading issue report.
Auto-discovery cache is a red herring. php artisan package:discover failing after an upgrade is almost always a stale bootstrap/cache/ or a genuine provider boot error, not a Composer problem. Delete bootstrap/cache/packages.php and bootstrap/cache/services.php and re-run before debugging further.
Extension points to prefer. If you need to bend package behaviour post-upgrade, reach for these in order:
vendor:publish, then override values. Cheapest, survives upgrades.Avoid subclassing package classes and binding your subclass over theirs: it is the first thing to break on the next compatibility release, and this release demonstrates that compatibility releases do happen.
Version-squatting risk on -W. When you run composer update -W, unrelated packages get bumped too. Run the upgrade on a branch, review composer.lock as a diff, and merge only after the test suite passes. -W is the right tool but it is not surgical.
How can I help you explore Laravel packages today?