Modern PHP Cheat Sheet aka Can I use?

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 breaks or returns.
  • 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)

Feature7.07.17.27.37.48.08.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