PHP is evolving steadily. Every year, there is a major new release containing new features, performance improvements, a fair share of deprecations, and even syntax changes. PHP core developers maintain the two latest PHP versions with active bug fixes and security fixes, followed by security fixes. This effectively means that each major PHP version will be supported at most for three years, and existing PHP applications are forced to upgrade.
While updating existing PHP applications is the ideal and recommended approach, inevitably, there are some applications/websites that cannot justify the human, political, and financial cost of the update. This is especially the case for legacy PHP applications that run on PHP 5 series or PHP 7 series. WordPress.org, for example, reports that only 16% of the reported WordPress sites run on a PHP version supported by the PHP core developers.
Updating a PHP application to be compatible with the latest PHP version is on a wide spectrum of difficulties. This can range from requiring no or little changes to what feels like a complete rewrite. PHP applications that were developed over a decade ago pose the biggest challenge because they tend to use PHP extensions that are no longer supported, have no type support, and often have no automated tests to verify the changes either.
Tools such as Rector can automate some, if not most, of the changes necessary, but extremely old PHP versions tend to require a lot of manual code updates.
In some cases, the cost of upgrading is not worth the effort and the cost. Some of the examples include internal applications that are only used within a private network, applications that are planned for a rewrite, and applications that the original developers are no longer working at the company. Realistically, these applications may never get updated; only eventually replaced.
Because PHP versions receive official updates for only up to three years, this can leave the applications vulnerable to security vulnerabilities that often affect these unmaintained PHP versions as well. PHP Platform-as-a-Product (PAAS) offerings and shared hosting providers also force updating to a recent PHP version which can leave the applications broken on the new PHP version as well.
This article discusses strategies for running legacy PHP applications on a secure PHP environment, with additional security precautions and maintenance, thus extending the lifetime of said PHP applications.
The more a PHP application stays locked into a PHP version, the steeper it gets to update. However, squeezing a few more years out of a legacy application until it is replaced is sometimes more realistically viable compared to updating a decades-old PHP application.
Shared Hosts and Platforms to a Private Server
Most shared and managed hosting platforms and PHP PaaS offerings usually only offer the current PHP versions, but do not support old PHP versions in the long term. This makes absolute sense because the old PHP versions are left unmaintained, and it can compromise the security of their servers in case a vulnerability is discovered that affects these unmaintained PHP versions.
If the hosting provider/PaaS provider no longer supports the required PHP version, it might make sense to shop around for a provider that supports a wide range of PHP versions.
CloudLinux is one of the commercial operating systems that shared/managed hosting providers use on their servers, and those providers likely enable CloudLinux's HardenedPHP feature. HardenedPHP is a feature in CloudLinux that the CloudLinux backports security fixes even after the official php.net team has marked a PHP version as EOL.
Another approach is maintaining a private server/cloud server and configuring it yourself. Maintaining a VPS/Cloud server comes with a maintenance burden, but most operating systems nowadays come with sane defaults, automatic updates, and more to take some of this burden away. However, this server maintenance may not be for everyone.
Debian LTS, Ubuntu LTS, Rocky Linux, and RHEL are a few Linux-based operating systems that provide PHP in their default repositories. They do not receive bug fixes from upstream, but security fixes are backported as applicable.
For example, Ubuntu 20.04 LTS includes PHP 7.4.3 in its default repositories. Ubuntu 20.04 LTS receives hardware and maintenance updates until 2025. PHP 7.4 is currently marked as End-Of-Life by the official php.net team, but the developers behind Ubuntu 20.04 back-port any security patches to the PHP version available in the repository. Any non-security bug fixes are not back-ported. This essentially means that the PHP version of Ubuntu 20.04 will remain as PHP 7.4.3, but with all the security fixes applied. Ubuntu's paid (free for five personal computers) Ubuntu Pro offering extends this with five additional years, which essentially means it is possible to securely run a PHP 7.4 application until 2030.
Web Server Integration
PHP integrates with web servers such as Apache, Nginx, Litespeed, Caddy, and more. When running a legacy PHP application, it is recommended to switch to php-fpm
as the server API. Apache, for example, supports running PHP as an Apache module, which hinders the ability to upgrade the Apache version in case the application must be run on an older PHP version.
Nginx and Caddy only integrate with php-fpm
, so no changes are necessary for them.
PHP also has a built-in server. It is unlikely that a production server uses it, but make sure to use a fully-fledged web server to add a separation between PHP and the web server.
Containerized PHP
When running a full LTS operating system (such as Ubuntu LTS) is not viable, an alternative approach would be using containers to run the required PHP version.
With containers, the rest of the file system and networking are left intact unless explicitly allowed. The PHP-FPM process can run inside a container with minimal file system access (session storage, temp files, file uploads, etc allowed), FPM port (for web server integration), and database ports allowed, but everything else remain within the container.
PECL Extension Replacements
Even if the operating system or a third-party repository provides PHP updates, it is unlikely that they offer security updates for EOL PHP extensions.
- PECL extensions that connect with external services such as SSH, FTP, Email, LDAP, etc are better off with user-land PHP implementations of them.
- Extensions offering cryptographic operations (
mcrypt
andopenssl
for example) are better replaced with newer extensions such asSodium
, or its user-land PHP polyfills. - PDF libraries (such as DomPDF) can be replaced with headless browsers or command-line tools such as wkhtmltopdf.
- Image generation extensions (such as Imagick and GD) can be replaced with CDNs that offer image manipulation.
Composer, PHP's dependency manager recently bumped its minimum PHP version requirement. However, Composer 2.2 is an LTS version of Composer 2, which should be supported for at least the end of 2023.
Composer is fairly conservative when it bumps up its minimum required PHP version, so it should be relatively trouble-free even on older PHP versions.
LTS Frameworks, Libraries, and local forks
PHP Frameworks and libraries such as Laravel, and Nette tend to be fast-moving frameworks while Symfony and Slim are more conservative.
- Although Laravel used to offer LTS releases that provided five years of security updates, recent Laravel versions only offer only one year of active support followed by a year of security fixes, so it might require manually porting security updates.
- Recent Drupal versions (such as Drupal 10) require recent PHP versions. Drupal 7 continues to receive support at the moment, but there are free and commercial Drupal LTS projects that provide coordinated security releases even after they officially reach EOL. For Drupal 7, there is also BackDrop CMS that provides an easy upgrade path.
- WordPress tries to maintain compatibility for older PHP versions, so updating to WordPress should be possible even on older PHP versions.
- Symfony (and its components) provide LTS versions with at least three years of security updates.
When a PHP library/framework abandons the version the PHP application depends on, it then becomes up to the maintainer of the PHP application to fork the repository and back-port security updates as they are made. Sharing that effort as a public project can pay forward the efforts others make maintaining other LTS packages. For private packages, a locally cloned repository or a private Composer repository can make the Composer integration work.