PHP 7 to 8: Entering the Modern Era of Programming Languages

March 03, 2022
Senior Developer

Let’s be honest, PHP is an old language, relatively speaking. It might not be as ancient as COBOL or Smalltalk, but it’s a dinosaur relative to the new generation of programming languages like Rust, Julia, or Typescript. Due to wide adoption and decades of maintaining legacy functionality, updating PHP to include newer features and runtime improvements takes significant time and consideration. The reality is this language is not going anywhere, and there are many benefits of upgrading to PHP 8.

PHP 8 includes improvements that show a clear desire to modernize, as well as capabilities of other popular languages that developers will appreciate. Thanks to PHP 8, Drupal 10 can now use tools that will enable continued growth and enhanced performance. Upgrading to PHP 8 will be beneficial to any site running on PHP–however, as a Drupal developer, I’m particularly excited about how this will impact Drupal 10. I’ll highlight some of the benefits that apply to many sites, but especially how it may apply to Drupal.

To make the most of your PHP upgrade, learn about all of the new and exciting features of this programming language.

Why Upgrade to PHP 8?

Before discussing the features of PHP 8, it’s important to understand why you will want to make this upgrade from PHP 7 to PHP 8. The short answer is that Drupal 10 is requiring a PHP upgrade to enforce requirements imposed by Symfony 6.

It’s also relevant to note that Drupal 10 specifically requires version 8.0.2, not version 8.1. For updates like Fibers and better JIT performance, be sure to use version 8.1 (as opposed to the minimum PHP version needed by Drupal 10). Conversations on this topic are still ongoing, so keep an eye out for updates as new versions of Drupal are released!

New Language Syntax

PHP 8 and 8.1 both introduced changes that can be generally split into three groups: language syntax, new functionality, and execution strategy improvements. Syntax changes give developers opportunities to write code that’s more expressive of what they are trying to do, often with fewer lines of code. 

If we can create the functionality we want with syntax we like, that not only benefits the quality of the sites we build but also helps us with the speed at which we can write code. This article will cover some of the most exciting syntax changes, but you can check out the full list of changes for PHP 8 and PHP 8.1.

Help with NULL

Accessing data from within a deeply nested structure can be a hassle. Values at keys within a PHP array or object can be NULL, and they need to be checked for this case since this can cause runtime errors if not properly addressed. The isset function has helped with this for years, but with the advent of object-oriented programming in PHP 7, lots of data accessing is done via class methods, and those do not play well inside of an isset call.

PHP 8 has added a popular solution to this problem with the nullsafe operator: ?-> (See Figure 1). Many other languages already have this operator, and its addition to PHP will allow us to access data more efficiently.

$data = new stdclass;
$data->foo = NULL;

var_dump($data->foo);
// result: NULL

var_dump($data->foo?->stuff);
// result: NULL

var_dump($data->foo->stuff);
// result: ERROR

Figure 1: The Nullsafe Operator

PHP also added special type operators for making custom types that can allow for more specificity in type declarations. One such operator is the union type operator (See Figure 2). In the spirit of taking inspiration from others, this syntax is the same as in TypeScript and Haskell’s type systems. Thanks to this update, a function or class method can now explicitly state if an argument can be exclusively one of two or more types as a part of its declaration. 

NULL can be included alongside types in a union type declaration, and when NULL isn't included it cannot be passed as a value to that argument. All of this helps developers better control cases with NULL values and helps reduce runtime errors and bugs.

function func(int|string $foo) {
    var_dump($foo);
}

func(5);
// result: 5

func('bar');
// result: 'bar'

func(NULL);
// result: ERROR

Figure 2: Union Type Operators

Match Statements

Switch statements have been a staple to PHP and several other languages for decades. PHP 8 includes an improved version of this age-old control structure: the match expression (See Figure 3). 

Match expressions function similarly to switch statements, but they differ significantly from switch statements in that they are expressions used to resolve to a value, instead of a statement that operates as a control structure that runs lines of code. Because of this, setting the value of a variable with the return value of a match statement when it is declared is now possible.

$bar = 8.0;

$foo = match($bar) {
    8 => 'int 8',
    8.0 => 'float 8',
    '8.0' => 'string'
};

var_dump($foo);
// result: float 8

Figure 3: Match Statements

Pattern matching is an integral concept in many strongly typed languages, such as Rust, Haskell, and OCaml. The addition of match statements to PHP indicates the language is taking inspiration from other languages when making improvements. Though PHP match expressions aren't quite as powerful as similar syntax in other languages, this is still a huge leap forward in modernizing PHP. 

The fact that they can return a value and don't need break statements should eliminate many unnecessary lines of code and allow for better readability. For switch statements, the default case was optional and could potentially lead to undesired cases if not handled properly. However, with match expressions, an error will be thrown when no default case is provided, naturally encouraging the creation of more secure code.

Pure Intersection Types

Pure intersection types were added in PHP 8.1 and they provide an interesting way of strengthening the object-oriented type system in PHP (See Figure 4). When an object that is being passed to a function needs to implement two or more specific interfaces, a pure type intersection operator can be used to combine those interfaces into one type. 

Instead of having to create a new interface in a separate file, intersection types can be easily created when needed. Having more opportunities to create new types allows developers to be more expressive with their code and improves legibility, which can save time and effort over the long run.

class Bar implements Stringable, Countable {
    function __toString() {
        return 'this is an object';
    }
    
    function count(): int {
        return 0;
    }
}

class Foo {
    public function __construct(
        public Stringable&Countable $bar
    ) {}
}

$foo = new Foo(new Bar());

var_dump('toString: ' . $foo->bar);
// result: 'toString: this is an object'

var_dump('count: ' . count($foo->bar));
// result: 'count: 0'

Figure 4: Pure Intersection Types

New Functionality

Aside from syntax, new functionality has been introduced in PHP 8 and 8.1 that provides an opportunity for Drupal to improve drastically. Namely fibers and class attributes present new ways to enhance underlying code directly.

Fibers

Another way that PHP has differed from several other server-side languages is through the lack of native support for managing concurrency or suspend execution of code. Using callbacks can allow developers to write asynchronous code. However, there is no API enforced by the language for this functionality; it's managed entirely by other packages. The addition of the Fiber class in PHP 8.1 opens a new world of non-blocking code possibilities. 

In the Drupal community, issue threads are getting traction as developers advocate for using fibers to make time-consuming tasks like cache rebuilds, queue runners, and automated cron runs more performant and easier to manage.

Despite some exciting use cases of fibers, we aren't likely to see them used extensively in the everyday development of Drupal. Even the PHP documentation states "Libraries will generally build further abstractions around Fibers, so there's no need to interact with them directly." Fibers are introduced through 8.1, so you might not see it in Drupal 10 core until 8.1 becomes the minimum version needed. PHP is striving to make up for lost time with fibers and we can expect to see revolutionary architectures in future applications thanks to their introduction in PHP 8.

Class Attributes

A huge improvement in Drupal 8 was the Plugin API, which includes a discovery system for finding plugin classes. PHP 8 class attributes can make this process even better. Several types of plugin discovery exist, such as Annotated Class Discovery. This discovery type makes use of a class annotation in a comment before a class definition. 

Since class metadata is inside of a comment, a separate library provided by the Symfony framework called Doctrine is needed to parse and use class annotations. With class attributes, this functionality is now a native part of the language. Class attributes allow for much more flexibility in specifying metadata for a class, without the use of a third-party library. 

Additionally, they can be used for tasks other than plugin discovery, since attributes can be placed on class methods as well. When used in that context, attributes can specify route handlers, event subscribers, and a whole range of other Drupal functionality. Other object-oriented languages like Java, C#, and even JavaScript have versions of class attributes. The addition of class attributes to PHP 8 is further proof that the language is striving to modernize and provide developers with tools to build better systems.

JIT Compilation

The maintainers of PHP might have added all kinds of new and cool syntax and functionality, but underneath it, all was still the same execution process of language parsing, AST creation, OPcode transpilation, OPcache, and execution inside a VM. Little had previously been done to enhance the step between the traditional Zend VM and the CPU, but with PHP 8 a new door has been opened. 

As hardware has gotten exponentially more powerful over time, compilation has gotten quicker and quicker. Because of this Lua, Python, JavaScript, and other transpiled languages have made use of a Just-In-Time (JIT) compilation step that happens after a script has been queued for execution and before it is actually executed. 

JIT compilers offer huge speed boosts since all optimization strategies that have been part of compilers, in general, can be applied to scripting languages as well. PHP 8 added a JIT compiler to the language, which will allow it to make huge strides in code performance in the same way that many other popular languages already benefit from.

While PHP will become much more performant with version 8, the web frameworks that use PHP won't see the same kind of speed boost. The limiting factors to server-side processing speed in Drupal will still be the same as they were before: database queries, bootstrapping on request, and other architectural constraints.

Benchmarks against other similar frameworks have shown only a 3-5 percent increase in page render speed, so the same can be safely assumed for Drupal. For functionality requiring complex processing that is written purely in PHP though, the JIT compiler will make a huge difference. Image processing and data analysis can now be reasonably implemented in PHP thanks to the new JIT compiler.

Switching to PHP 8

As always, teams will need to rigorously test their sites with new versions of PHP locally, as well as in higher-level environments afterward. Switching to PHP 8 is possible to do today under Drupal 9 and is fairly easy to do locally, especially if you’re using Lando and Drupal VM. Configuring the PHP version used by an environment in Acquia Cloud is also a relatively straightforward task.

Whether it’s using new syntax, experiencing the speed boosts of the JIT compiler, or trying out new features of the language, PHP 8 has many improvements for developers to be excited about. PHP is continually improving, and keeping up with its growth will make for a better Drupal experience, which in turn will make the life of developers easier as well. I recommend upgrading to PHP 8 and giving all of these new and modern features a try as soon as you can!