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=true

The 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.

PHP 8.5 deprecations likely to appear in a Laravel application
DeprecatedUse insteadWhere to look
$array[null]An empty string keyArray 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 callHand-written API clients
finfo_close(), imagedestroy(), xml_parser_free()Remove the callUpload handling, image resizing, XML feeds
$http_response_headerhttp_get_last_response_headers()file_get_contents() calls to URLs
Reflection setAccessible()Remove the call, as it no longer does anythingTests 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] = $value raises a warning when $value isn’t an array, except for null.
  • Session keys. A $_SESSION key 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_LATE without PDO::FETCH_CLASS, or PDO::FETCH_INTO in fetchAll(), now throws a ValueError. 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.so line 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

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.

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).