Laravel upgrades
Laravel on PHP 8.5: what actually breaks
On a supported Laravel version, very little breaks outright on PHP 8.5. Most of the changes are deprecations, which show up as log entries rather than errors, and Laravel discards those logs by default. So turn them on before you decide the move went smoothly.
By itmarkerz Technologies. Updated 30 October 2026.
Which Laravel versions support it
Laravel’s support table lists PHP 8.5 for Laravel 12 and 13 only. A cabinet manufacturer’s system we upgraded runs on Laravel 13 and PHP 8.5, so this isn’t a theoretical combination.
Watch out for what Composer allows. The framework’s PHP requirement is open-ended (^8.2 on Laravel 11), so Composer will install Laravel 11 on PHP 8.5 even though Laravel doesn’t list that pairing. A clean install tells you nothing here.
First, make deprecations visible
Laravel sends PHP deprecations to its own log channel, and in the current skeleton that channel defaults to null. Unless you’ve set it, they go nowhere. On staging, add this to your .env:
LOG_DEPRECATIONS_CHANNEL=single
LOG_DEPRECATIONS_TRACE=trueThe trace matters, as it tells you whether the caller is your code or a package in vendor. Run your tests and click through your main flows, then read the log. Deprecated code keeps working today, but PHP’s pattern is to remove deprecated features in a later major version, so you’re clearing tomorrow’s fatal errors.
The one nearly everyone hits: PDO constants
PHP 8.5 deprecates the driver-specific PDO constants, and that reaches the framework’s own config file. Laravel’s skeletons show the change clearly: the 11.x file uses PDO::MYSQL_ATTR_SSL_CA, the 12.x file checks the PHP version, and the 13.x file uses the new name alone. Upgraded applications keep their old config unless someone changes it, so yours may still have the 11.x line even on Laravel 13.
While you still need to run on older PHP, use the form from the 12.x skeleton, in both the MySQL and MariaDB blocks:
use Pdo\Mysql;
// In the 'options' array of each connection:
(PHP_VERSION_ID >= 80500 ? Mysql::ATTR_SSL_CA : PDO::MYSQL_ATTR_SSL_CA) => env('MYSQL_ATTR_SSL_CA'),The other PDO names follow the same pattern. If your code sets PDO::MYSQL_ATTR_USE_BUFFERED_QUERY, PDO::MYSQL_ATTR_INIT_COMMAND or an SSL option, search for MYSQL_ATTR_ across the project. Older calls on the PDO object itself, such as sqliteCreateFunction() and pgsqlCopyFromArray(), are deprecated too.
Deprecations worth searching for
This is our selection from php.net’s list, chosen for how often these patterns appear in application code.
| Deprecated | Use instead | Where to look |
|---|---|---|
$array[null] | An empty string key | Array building from nullable values, including array_key_exists() |
(integer), (boolean), (double), (binary) | (int), (bool), (float), (string) | Old code. Search for the cast names |
Backticks: `ls` | shell_exec() | Deploy scripts, Artisan commands, reporting jobs |
curl_close() | Remove the call | Hand-written API clients |
finfo_close(), imagedestroy(), xml_parser_free() | Remove the call | Upload handling, image resizing, XML feeds |
$http_response_header | http_get_last_response_headers() | file_get_contents() calls to URLs |
Reflection setAccessible() | Remove the call, as it no longer does anything | Tests and older helpers |
SplObjectStorage::attach(), detach(), contains() | offsetSet(), offsetUnset(), offsetExists() | Custom collections and event listeners |
case 1; | case 1: | A semicolon after case in a switch |
__sleep(), __wakeup() | __serialize(), __unserialize() | Soft-deprecated. Queued objects and cached models with custom serialisation |
Most of these are quick to fix once you’ve found them. The null array offset is the exception. It usually points at a value that was never meant to be null, so fixing it properly means working out why it is.
What can change behaviour
These come from php.net’s backward-incompatible changes. They’re the items more likely to show up as a real difference rather than a log line.
- Float to integer casts. Casting a float that can’t be represented as an integer now raises a warning. With Laravel’s error handler, a warning in the wrong place becomes an exception, so check imports and calculations that handle very large numbers.
- Destructuring non-arrays.
[$a, $b] = $valueraises a warning when$valueisn’t an array, except fornull. - Session keys. A
$_SESSIONkey containing|now raises a warning. Laravel manages its own sessions, so this mainly affects older code that uses native PHP sessions directly. - PDO fetch modes. Using
PDO::FETCH_PROPS_LATEwithoutPDO::FETCH_CLASS, orPDO::FETCH_INTOinfetchAll(), now throws aValueError. Eloquent doesn’t need you to set these, so only hand-written PDO code is affected. - OPcache config. OPcache is now always built in, so a leftover
zend_extension=opcache.soline in your PHP config emits a warning. Fix it in the server image.
Packages
Run composer why-not php 8.5 to see any package with a PHP ceiling. Few have one: inertiajs/inertia-laravel 1.x is an example, as its constraint stops at 8.4. A package with an open-ended constraint will install either way, whether or not its maintainer has tried PHP 8.5. That’s why the deprecation log is a better test than Composer. Our package compatibility matrix shows each constraint, and the PHP matrix covers the framework side.
Is it worth going to 8.5?
If you’re moving off PHP 8.2 before its deadline and want the simplest route, PHP 8.4 means fewer changes and still has support until the end of 2028. PHP 8.5 buys another year, to the end of 2029. It makes sense if you’re already doing a larger upgrade and would rather clear the deprecations once, while someone is already reading the code.
Upgrades we have delivered
Cabinet manufacturer's ordering, dealer-portal and inventory system moved from PHP 5.6 and MySQL 5.0 to Laravel 13 on PHP 8.5 and MySQL 8, with a new Next.js front end. Eight months, workflows preserved, now live.
- Sector
- Manufacturing
- Region
- Canada and US
- Stack
- Laravel 13, PHP 8.5, MySQL 8, Next.js
- Engagement
- Upgrade, about eight months, live
Loyalty-card management system we first built on PHP 5.6, re-platformed onto Laravel with all cards, balances and rules preserved. Two months, live since mid-2026, Indian client.
- Sector
- Retail & loyalty
- Region
- India
- Year
- 2026
- Stack
- Laravel
- Engagement
- Upgrade of our own earlier build, two months
Questions
Does Laravel 12 support PHP 8.5?
Yes. Laravel’s support table lists PHP 8.2–8.5 for Laravel 12 and PHP 8.3–8.5 for Laravel 13. Laravel 11 stops at 8.4, and Laravel 10 at 8.3.
Why do I see a PDO::MYSQL_ATTR_SSL_CA deprecation?
PHP 8.5 deprecates PDO’s driver-specific constants in favour of ones on the driver class, such as Pdo\Mysql::ATTR_SSL_CA. A config/database.php file from an older Laravel skeleton still uses the old name. It’s a notice, and your connection still works, but the file should be updated.
Can I run Laravel 11 on PHP 8.5?
Composer may let you, because the framework’s own constraint is open-ended, but it isn’t supported. Laravel lists PHP 8.2–8.4 for that version, and its security fixes ended on March 12, 2026. Upgrade the framework rather than running this combination.
Should I move to PHP 8.5 now?
Only if you have a reason, such as wanting the longest support window, which runs to 31 December 2029. PHP 8.4 has support until the end of 2028 and fewer deprecations to clear. If you do go to 8.5, test with deprecations visible first.
More on Laravel upgrades
- Laravel package compatibility matrixWhich release of each common package allows which Laravel and PHP version.
- Laravel 12 end of life: what to do firstThe security deadline, and the two things that block Laravel 13.
- PHP 8.2 end of life for Laravel teamsChoosing between PHP 8.3, 8.4 and 8.5 before the deadline.
- Upgrading from Laravel 11 to 12Carbon 3, UUIDs and file paths: the changes that throw no errors.
- Upgrading from Laravel 10 to 11You can keep your structure. Here’s what you can’t keep.
- Upgrading Laravel 5–9Step through each version, move to a fresh install, or rebuild.
- Laravel Shift or an upgrade teamWhen an automated tool is enough, and when it isn’t.
- Filament upgrade path to Laravel 13Which order to move in from Filament 2, 3, 4 or 5.
- Which Laravel version do you need for the AI SDK?The version floors, and what to do if you’re below them.
- Laravel 14: release window and how to planWhat’s known, what isn’t, and what to do today.
- Inherited a Laravel app? The first 10 daysAccess, backups, an inventory and a safe deploy, before any new features.
- Laravel 11 end of life: what to do nowStop at Laravel 12 or go straight to 13.
- Laravel 10 end of life: your upgrade optionsFour routes off Laravel 10, and the breaking changes in the first step.
- How much does a Laravel upgrade cost?Our published prices by application size, and what moves a quote.
- Upgrading from Laravel 12 to 13The changes that matter, in the order we would check them.
- PHP 8.1 end of life and LaravelWhy PHP can move before the framework does.
- Laravel upgrade checklistEvery step from inventory to the first week after release.
- Laravel vs Symfony: an upgrade decisionSupport windows compared, and when changing framework makes sense.
Planning a PHP 8.5 move?
Tell us your Laravel version and your main packages. We’ll tell you what to expect, and what it would cost us to do it.
We reply within one business day (IST).