2022-02-06: Now updated for PHP 8.1.
PHP 8.0 was released at the end of 2020. It comes with an improved performance, some nice additions to the syntax and it also fixes some of the annoying quirks of its predecessors. Which is great … if it weren’t for that Huge Legacy Application you have to maintain, which is forever stuck on PHP 5.6 because it relies heavily on some long gone features. But it is not that bad, because it will soon be replaced by The New Application. At least that’s what we thought when PHP 7.0 came around.
There is also That Other Application which is already on 7.0. That means it has all the new and shiny features. Well, not exactly new, as PHP 7.0 was released in 2015! But somehow you still consider this to be modern because, you know, PHP 7! It’s a commercial software, newer versions are available. Sadly someone decided to make lots of changes to it. So no upgrades for us.
Luckily there is The New Application. A greenfield project. Well, kind of. It should replace both of the other applications. It also needs to work with the rest of the company infrastructure. So there are lots of constraints. But it is still new and fresh and state of the art. Well, at least it was, when it was started. It uses PHP7.3, which is only just out of the support period. Of course we could upgrade it. And we will. Soon.
On any given day there might be some fixes for the Huge Legacy System. Just before lunch you get a code review from a colleague who has the pleasure to support That Other Application. At lunch time you read about PHP 8’s additions to the syntax. Tonight you finally going to upgrade that pet project of yours. (Of course that’s what you keep telling yourself since last year ;-)) Lunch is followed by some meetings but at the end of the day you finally get to work on The New Application.
You are switching back and forth between half a dozen PHP releases, never quite sure about what feature you can and cannot use.
Help is coming
To fix this once and for all here is the PHP Feature Cheat Sheet covering the major changes introduced since PHP 7.0. Each version added some new syntax elements, others were deprecated or even removed. There were also lots of changes to the standard functions.
Note: This is not a comprehensive list of all the changes but highly biased based on my own experience.
The Cheat Sheet
PHP 7.0
The complete list of changes introduced with 7.0 can be found here.
Type declarations
To me the most important change to the language: starting with 7.0 the type system was greatly improved. You could already use class names, interfaces or array
for function arguments since PHP 5. 7.0 added scalar type declarations as well as return type declarations (typed class properties where introduced in 7.4).
Throwable
Throwable
was introduced as the base interface for anything that can be thrown. Ever wondered why some exception escaped your try-catch block? Most likely it was an Error
and you only mentioned Exception
in the catch part. Only Throwable
will really catch everything.
Operators
Two operators where added: the null coalescing operator (??) and the spaceship operator (<=>).
The null coalescing operator is a shorthand expression for using the ternary operator together with isset
. It returns the first operand if it exists and is not null, otherwise it returns the second operand.
The spaceship operator is used to compare two expressions. It will return -1 if the first operand is smaller than the second, 0 if they are equal and 1 if the first operand is bigger than the second. It can be used on numbers and strings.
PHP 7.1
The complete list of changes introduced with 7.1 can be found here.
Nullable types
One thing 7.0 was missing were nullable types. Starting with 7.1 parameters and return values can be marked as nullable. This means you could also pass (or return) null as well as the specified type.
Void functions
Another addition to the type system: void functions. Functions can now be marked to return no value.
Class constant visibility
Not really a major new feature but as it is demanded by several code style tools it gets an honorable mention.
Multi catch exception handling
The ability to specify multiple exception types in one catch block allows for more flexibility and might also save some lines of code.
PHP 7.2
The complete list of changes introduced with 7.2 can be found here.
Object type
Object
was added to the type system. It can be used for function parameters and return types.
PHP 7.3
The complete list of changes introduced with 7.3 can be found here.
Trailing Commas in Function Calls
The ability to add trailing commas allows for nicer diffs in multiline function calls. Which is also true for multiline arrays.
Continue Targeting Switch issues Warning
This change made the list because it affected composer itself as well as several prominent packages. I’ve seen this way to often.
JSON_THROW_ON_ERROR
This flag can be used with json_encode
or json_decode
. Both functions will throw a JsonException
instead of setting the global error state which has to be checked using the JSON error functions.
PHP 7.4
The complete list of changes introduced with 7.4 can be found here.
Typed properties
Class properties can now be typed as well.
Arrow functions
Arrow functions were introduced as a shorthand for anonymous functions aka closures. One slight difference: arrow function can always access variables from the parent scope. No need for the use
keyword.
Null coalescing assignment operator
As the name suggests, it combines the null coalescing operator with an assignment. See an example here.
PHP 8.0
The complete list of changes introduced with 8.0 can be found here.
Named arguments
This allows to pass arguments to a function based on the parameter name instead of the position. This means you can pass arguments in any order and you can skip arguments with default values. It also adds so meaning to the arguments.
Attributes
Attributes allow us to add metadata on declarations. They can be evaluated using reflection. They are pretty similar to annotations but they are now part of the core language. That means the over better performance and are more reliable.
Constructor Property Promotion
A lot of constructors are pretty boring. They simply assign the parameters to the class properties. Constructor promotion offers a short-hand syntax for this.
Union Types
Union type declaration allow us to use multiple different types. In early versions you would need to omit the type declaration in these cases and could only list the allowed types in the doc block. Now, this is part of the syntax.
Match Expression
This is somewhere between a switch
statement and a ternary expression mixed with arrow functions.
- It is an expression, so it evaluates to a value.
- Unlike switch it uses an identity check.
- There is no fall-through to later cases.
- Cases can be combined by listing multiple expressions separated by a comma
- There are no
break
s orreturn
s. - The expression must be exhaustive.
- There is also a
default
pattern.
Nullsafe Operator
This comes in handy for chained method calls. If one part of the chain returns null, the rest is skipped and null is returned. In earlier versions this would result in an exception.
String functions
str_contains
, str_starts_with
and str_ends_with
functions where added. You could to this before, but the new functions offer a more intuitive interface.
PHP 8.1
The complete list of changes introduced with 8.1 can be found here.
Enumerations
With enumerations you can replace all those constants and get validation out of the box.
Readonly Properties
Properties can be marked as readonly, which means they cannot be changed after being initialized.
New in initializers
This allows for using objects as default values.
Intersection types
Similar to union types, you can now specify type constraints as the intersection of types. Combining the two is not possible.
Never return type
This marks a function that will never return (because it throws an exception or uses die
or exit
).
Can I use?
To make it even easier to figure out which feature you can use with which version, I added this handy table (slightly inspired by caniuse.com)
Feature | 7.0 | 7.1 | 7.2 | 7.3 | 7.4 | 8.0 | 8.1 |
---|---|---|---|---|---|---|---|
Scalar type declarations | ✅ | ✅ | ✅ | ✅ | ✅ | ✅ | ✅ |
Return type declarations | ✅ | ✅ | ✅ | ✅ | ✅ | ✅ | ✅ |
Throwable | ✅ | ✅ | ✅ | ✅ | ✅ | ✅ | ✅ |
Null coalescing operator (??) | ✅ | ✅ | ✅ | ✅ | ✅ | ✅ | ✅ |
Spaceship operator (<=>) | ✅ | ✅ | ✅ | ✅ | ✅ | ✅ | ✅ |
Nullable types | ❌ | ✅ | ✅ | ✅ | ✅ | ✅ | ✅ |
Void function | ❌ | ✅ | ✅ | ✅ | ✅ | ✅ | ✅ |
Class constant visibility | ❌ | ✅ | ✅ | ✅ | ✅ | ✅ | ✅ |
Multi catch exception handling | ❌ | ✅ | ✅ | ✅ | ✅ | ✅ | ✅ |
Object type | ❌ | ❌ | ✅ | ✅ | ✅ | ✅ | ✅ |
Trailing commas in function calls | ❌ | ❌ | ❌ | ✅ | ✅ | ✅ | ✅ |
Continue targeting switch issues warning | ❌ | ❌ | ❌ | ✅ | ✅ | ✅ | ✅ |
JSON_THROW_ON_ERROR | ❌ | ❌ | ❌ | ✅ | ✅ | ✅ | ✅ |
Typed properties | ❌ | ❌ | ❌ | ❌ | ✅ | ✅ | ✅ |
Arrow functions | ❌ | ❌ | ❌ | ❌ | ✅ | ✅ | ✅ |
Null coalescing assignment operator | ❌ | ❌ | ❌ | ❌ | ✅ | ✅ | ✅ |
Named arguments | ❌ | ❌ | ❌ | ❌ | ❌ | ✅ | ✅ |
Attributes | ❌ | ❌ | ❌ | ❌ | ❌ | ✅ | ✅ |
Constructor property promotion | ❌ | ❌ | ❌ | ❌ | ❌ | ✅ | ✅ |
Union types | ❌ | ❌ | ❌ | ❌ | ❌ | ✅ | ✅ |
Match expression | ❌ | ❌ | ❌ | ❌ | ❌ | ✅ | ✅ |
Nullsafe operator | ❌ | ❌ | ❌ | ❌ | ❌ | ✅ | ✅ |
String functions (str_contains , str_starts_with , str_ends_with ) | ❌ | ❌ | ❌ | ❌ | ❌ | ✅ | ✅ |
Enumerations | ❌ | ❌ | ❌ | ❌ | ❌ | ❌ | ✅ |
Readonly Properties | ❌ | ❌ | ❌ | ❌ | ❌ | ❌ | ✅ |
New in initializers | ❌ | ❌ | ❌ | ❌ | ❌ | ❌ | ✅ |
Intersection types | ❌ | ❌ | ❌ | ❌ | ❌ | ❌ | ✅ |
Never return type | ❌ | ❌ | ❌ | ❌ | ❌ | ❌ | ✅ |