End of PHP 8.2 support: migrate to PHP 8.4 or 8.5 before 2027
PHP 8.2 support ends on 31 December 2026: which version to target, Symfony, Laravel, WordPress and Drupal compatibility, tools and step-by-step migration.
PHP 8.2 support ends on 31 December 2026: from that date, the PHP project will no longer fix any vulnerabilities. If your Symfony, Laravel, WordPress, Drupal or PrestaShop applications still run on 8.2, here is the version to target, the compatibility points to check, the tools to use and a tested migration method, with the FrankenPHP option.
PHP 8.2: what happens on 31 December 2026
Each PHP branch gets two years of active support, then two years of security fixes only. For PHP 8.2, released on 8 December 2022, active support ended on 31 December 2024 and security fixes stop on 31 December 2026, according to php.net. As of 19 September 2026, the latest release is 8.2.33, from 30 July 2026.
| Branch | Release | Active support until | Security until |
|---|---|---|---|
| 8.2 | 8 Dec 2022 | 31 Dec 2024 | 31 Dec 2026 |
| 8.3 | 23 Nov 2023 | 31 Dec 2025 | 31 Dec 2027 |
| 8.4 | 21 Nov 2024 | 31 Dec 2026 | 31 Dec 2028 |
| 8.5 | 20 Nov 2025 | 31 Dec 2027 | 31 Dec 2029 |
| 8.6 | Planned for 19 Nov 2026 | Not published | Not published |
The PHP 8.6 schedule provides for four release candidates between 24 September and 5 November 2026. At the time of publication, 8.6 is therefore not yet stable.
Why staying on an end-of-life version is a risk
Security. A vulnerability found in 2027 in the PHP engine or a standard extension will not be fixed in 8.2. Your exposure depends on your code, but you lose the simplest lever: applying a fix.
Dependencies. Frameworks and libraries drop end-of-life PHP versions. Staying on 8.2 means eventually condemning yourself to dependency versions that no longer receive fixes themselves.
Compliance. The Cyber Resilience Act (Regulation (EU) 2024/2847) requires manufacturers of products with digital elements to handle vulnerabilities in their components, including open source ones, throughout the support period. Its reporting obligations have applied since 11 September 2026, the rest from 11 December 2027 (European Commission). A software vendor shipping software built on a runtime with no fixes will struggle to meet these commitments; we detail these obligations in our article on the Cyber Resilience Act. For a custom website or application, what mainly applies is the general obligation to secure personal data (Article 32 of the GDPR).
Contracts. If you are a service provider, check your application maintenance (TMA) contracts: a “security maintenance” commitment is hard to honour on a platform that nobody fixes any more. It is better to plan the upgrade than to discover it during a customer audit.
Which version to target: 8.4 or 8.5?
| Criterion | PHP 8.4 | PHP 8.5 |
|---|---|---|
| End of security fixes | 31 Dec 2028 | 31 Dec 2029 |
| Track record in production | Almost two years | Under a year |
| CMS compatibility | Broad (WordPress, Drupal 10.4+ and 11, PrestaShop 9.0) | WordPress 6.9+, Drupal 11.3+, PrestaShop 9.1 |
| Frameworks | Laravel 12 and 13; required by Symfony 8.x | Laravel 12 and 13 |
| When to choose it | Mixed estate, old dependencies, many third-party modules | Up-to-date project, Drupal 12 on the horizon, long horizon |
Our rule: target the most recent version that all your dependencies officially support. Jumping straight from 8.2 to 8.4 or 8.5 works perfectly well; there is no need to go through each intermediate version in production.
Framework and CMS compatibility
| Platform | Version | PHP required | End of support for the platform |
|---|---|---|---|
| Symfony | 6.4 LTS | ≥ 8.1 | Security until November 2027 |
| Symfony | 7.4 LTS | ≥ 8.2 | Bug fixes until November 2028, security until November 2029 |
| Symfony | 8.0 | ≥ 8.4 | End of maintenance in July 2026 |
| Symfony | 8.1 | ≥ 8.4 | January 2027 (8.2 planned for November 2026) |
| Laravel | 11 | 8.2 – 8.4 | Security support ended on 12 March 2026 |
| Laravel | 12 | 8.2 – 8.5 | Security until 24 February 2027 |
| Laravel | 13 | 8.3 – 8.5 | Security until 17 March 2028 |
| WordPress | 7.0 (20 May 2026) | Minimum 7.4, recommended 8.3+, compatible up to 8.5 | — |
| Drupal | 10 | 8.1 – 8.4 | End of life on 9 December 2026 |
| Drupal | 11 | ≥ 8.3 (8.5 from 11.3) | — |
| Drupal | 12 | ≥ 8.5 | Release planned for the week of 7 December 2026 |
| PrestaShop | 9.0 | 8.1 – 8.4 (8.4 recommended) | — |
| PrestaShop | 9.1 | 8.1 – 8.5 (8.5 recommended) | — |
Sources: Symfony, Laravel, WordPress, Drupal, PrestaShop.
Two cases deserve particular attention. Laravel 11 combines two end-of-life dates: the framework’s and, soon, PHP 8.2’s. Drupal 10 reaches end of life on 9 December 2026, three weeks before PHP 8.2: migrating to Drupal 11 and PHP 8.3 minimum is one and the same project. For WordPress, the core keeps up; it is the plugins and themes that decide.
What breaks in practice
To 8.3: few breaking changes. The new features (typed class constants, json_validate()) are optional.
To 8.4 (official list):
- implicitly nullable parameters (
string $x = null) are deprecated: write?string $x = nullinstead; exit()anddie()behave like functions and throw aTypeErroron an invalid type;- the
E_STRICTconstant is deprecated; - the IMAP, OCI8, PDO_OCI and pspell extensions are no longer bundled with PHP and move to PECL: a blocking point for applications that read mailboxes over IMAP;
- many functions now throw
ValueErrororTypeErroron invalid arguments.
To 8.5 (deprecations): the backtick operator, non-canonical cast names ((integer), (boolean)), case terminated by a semicolon, null as an array key, __sleep() and __wakeup(), curl_close() and imagedestroy(), among others. Deprecations, not errors: they will break in PHP 9, not now.
Migration tools
| Tool | Role | Command or configuration |
|---|---|---|
| Composer | Find the dependencies that block | composer why-not php 8.4 then composer outdated --direct |
| Rector | Rewrite the code automatically | withPhpSets(php84: true) |
| PHPStan | Detect type errors and invalid calls | phpVersion: 80400 |
| PHPCompatibility | Flag removed or deprecated functions | Branch 10 still in alpha as of 19 September 2026 |
| Composer audit | List known vulnerabilities in dependencies | composer audit |
To simulate dependency resolution on the target version without changing machine, declare the platform in a dedicated branch:
composer config platform.php 8.4.0
composer update --dry-run
composer why-not php 8.4Each package flagged must be updated, replaced or, as a last resort, forked. This is often where the real cost of the migration hides.
Minimal Rector configuration:
<?php
// rector.php
use Rector\Config\RectorConfig;
return RectorConfig::configure()
->withPaths([__DIR__ . '/src', __DIR__ . '/tests'])
->withPhpSets(php84: true);Start by running vendor/bin/rector process --dry-run, review the diff, then apply in batches. For PHPStan:
parameters:
level: 6
paths: [src, tests]
phpVersion: 80400Step-by-step migration method
- Take inventory. PHP versions per environment, loaded extensions (
php -m), Composer dependencies, CMS modules and extensions, scheduled tasks, workers. This is the first step of a migration audit. - Choose the target with the compatibility table, dependency by dependency.
- Add the target to the CI without blocking: a matrix that tests the current version and the target.
strategy:
matrix:
php: ['8.2', '8.4']
steps:
- uses: actions/checkout@v4
- uses: shivammathur/setup-php@v2
with:
php-version: ${{ matrix.php }}
- run: composer install --no-progress
- run: vendor/bin/phpunit- Log deprecations in pre-production (
error_reporting = E_ALL, dedicated channel:LOG_DEPRECATIONS_CHANNELon Laravel, Monolog’sdeprecationchannel on Symfony). - Update the blocking dependencies, then run Rector and PHPStan.
- Test following the plan below.
- Switch over gradually: one instance or site first, watch errors and performance, then roll out. Keep the old image ready for a quick rollback.
- Clean up: remove 8.2 from the CI, update the documentation and the maintenance contract.
FrankenPHP: change runtime during the migration?
FrankenPHP is a PHP application server written in Go, built on Caddy; its repository is hosted in the PHP project’s GitHub organisation. Its worker mode loads the application once and keeps it in memory between requests.
In the EXP-02 sheet of the iones lab, we developed the same orders API (6 endpoints, 2 million PostgreSQL rows, 4 vCPUs) in four languages. Results that are useful for deciding:
| Measure | Result |
|---|---|
| FrankenPHP worker vs PHP-FPM | Throughput multiplied by 3, with no code changes |
| Throughput without database, PHP | 9,800 req/s (Node 12,900, Go 31,200, Rust 38,400) |
| Throughput with database, mixed 80/20 load | All languages plateau between 3,800 and 4,100 req/s: PostgreSQL saturates |
| PHP p99 latency | 85 ms (Node 70 ms, Go and Rust under 45 ms) |
| Development time | PHP 11 hours, Node 13 hours, Go 19 hours, Rust 35 hours |
An honest reading: the worker-mode gain is real when application start-up is heavy; it disappears when the database is the bottleneck. Our decision after EXP-02: FrankenPHP for new PHP projects and for migrations from PHP-FPM.
Implementation with Symfony 7.4 or later, which natively supports worker mode:
docker run -e FRANKENPHP_CONFIG="worker ./public/index.php" \
-v $PWD:/app -p 80:80 -p 443:443 -p 443:443/udp dunglas/frankenphpWith Laravel, via Octane: composer require laravel/octane, then php artisan octane:install --server=frankenphp. Octane restarts each worker after 500 requests by default, adjustable with --max-requests.
Two pitfalls: shared state (static properties, singletons that keep the previous request or user) and memory leaks, hidden until now by PHP-FPM. Do the version migration first and the runtime change afterwards: two changes at once make diagnosis harder.
Test plan
| Level | Objective | Tools |
|---|---|---|
| Static analysis | Zero new errors at the chosen PHPStan level | PHPStan, SonarQube |
| Unit and integration tests | Green suite on both versions in the matrix | PHPUnit or Pest |
| Critical journeys | Login, order, payment, back office, exports | Playwright |
| Asynchronous tasks | Workers, message queues, crons, emails, IMAP reading | Dedicated scenarios in pre-production |
| Performance | No regression in p95/p99 latency or memory | Load test, Grafana |
| Production | Error rate and deprecations monitored after switchover | Logs, Grafana |
Frequently asked questions
When does PHP 8.2 support end?
Should you migrate to PHP 8.4 or PHP 8.5?
Can you go straight from PHP 8.2 to PHP 8.4?
Which PHP version for WordPress 7.0?
What is the risk of staying on PHP 8.2 in 2027?
Is FrankenPHP ready for production?
PHP 8.2 at end of life: plan the migration now
Less than three months remain before PHP 8.2 support ends. The path is known: inventory, choosing the target according to your dependencies, CI on two versions, Rector and PHPStan, tests of the critical journeys, gradual switchover. Take the opportunity to evaluate FrankenPHP, once the migration has stabilised.
Do you manage a portfolio of PHP applications, directly or for your agency clients? Our team carries out the audit, migration and maintenance, including under white label. Let’s talk about your migration plan: reply within 48 to 72 hours.
Sources
- Supported Versions – php.net
- Unsupported Branches – php.net
- PHP 8.6 release timeline – wiki.php.net
- Migrating from PHP 8.3.x to PHP 8.4.x – php.net
- PHP 8.5 deprecated features – php.net
- Symfony releases – Symfony
- Laravel 13 release notes – Laravel
- PHP Compatibility and WordPress Versions – WordPress.org
- Drupal core release schedule – Drupal.org
- Announcing Drupal 12.0.0 platform requirements – Drupal.org, January 2026
- System requirements for PrestaShop 9 – PrestaShop
- FrankenPHP worker mode – FrankenPHP
- Laravel Octane – Laravel
- Cyber Resilience Act – European Commission
- EXP-02 – Node, Go, Rust and PHP runtimes – iones lab