CodeLair website tutorials, articles & scripts

PHP new syntax reference

Published: 31 January 2020   •   Updated: 29 May 2023   •   Tags: php

PHP is under constant development and introduces several new language features with every release. As such, it can be difficult keeping track of them all and remembering which features can be used in which version. If you are using a slightly older version of PHP you’ll need to make sure you don’t start using syntax that’s not yet available in your version.

The same goes if your server uses a different version of PHP to your development environment (although there are better ways to solve that problem such as Docker or Vagrant), or if you’re an open source developer supporting a certain version of PHP. So below we list the major syntax changes in each version along with a short example.

This article continues to be updated with newer PHP versions.


PHP 8.2 #

Deprecate dynamic properties

Quite a big change that will affect many PHP apps. Properties on classes that are not defined are not allowed to be set (it will cause a deprecation notice). The generic stdClass or classes with __get/__set magic methods are not affected. Notices can be suppressed with the #[\AllowDynamicProperties] attribute.

class Foo
{
public $bar;
}

$foo = new Foo;
$foo->hello = 'world'; // Deprecation notice

Read-only classes

A class can be marked as readonly, which makes all of its properties read-only (their values cannot be reassigned after initilization). The class can be extended, but the child class must also be readonly, and its properties cannot be modified.

readonly class Foo
{
public string $bar = 'bar';
}

$foo = new Foo();
$foo->bar = 'test'; // error

Combine union and intersection types

Union types were introduced in PHP 8.0 and intersection types in 8.1. Now they can be combined - note that intersection types must always be wrapped in parentheses. Also known as Disjunctive Normal Form.

function foo((Iterator&Countable)|array $arrayLike)
{
// can loop the variable
foreach ($arrayLike as $val) { ... }

// can get its size
count($arrayLike);
}

Null, True or False as return types

The keywords null, true or false can be used as a return type, for functions that always return that value.

function foo(): false
{
return false;
}

Constants in traits

Traits can now include constants, which are available in any class that uses the trait.

trait Foo
{
public const BAZ = 'baz';
}
class Bar
{
use Foo;
}

$baz = Bar::BAZ;

Full list of 8.2 features


PHP 8.1 #

Enums

Enumerations can be used to hold a set of fixed values and refer to them.

enum Suit {
case Clubs;
case Diamonds;
case Hearts;
case Spades;
}

$suit = Suit::Diamonds;

Intersection types

Function/method parameters can type hint for multiple interfaces, and the object passed to it must implement both interfaces.

function foo(Iterator&Countable $arrayLikeObject)
{
// can loop the variable
foreach ($arrayLikeObject as $val) { ... }

// can get its size
count($arrayLikeObject);
}

Never return type hint

A new type hint that specifies a function will never return to the caller, i.e. it will use die or exit.

function redirect($url): never
{
header("Location: $url");
exit;
}

Read-only properties

Class properties can be set to readonly which means they cannot be reassigned after first initialization.

class Foo
{
public readonly string $bar;

public function __construct(string $bar)
{
$this->bar = $bar; // initial assignment ok
}
}

$foo = new Foo('test');
// cannot do this:
$foo->bar = 'something else';

First-class callable syntax

Obtain a true callable for any function or method. Useful for passing to functions requiring a callable, without the need to wrap it in another closure. Note: it uses literal ... in the syntax as a placeholder for the function parameters.

$len = strlen(...);
$len('my string');
$method = $object->foo(...);
$method('my string');
// equivalent to this, which doesn't work in all scenarios:
$len = 'strlen';
$len('my string');
$method = [$object, 'foo'];
$method('my string');

Named arguments after unpacking

Named arguments were added in PHP 8.0. They can now be used after argument unpacking.

foo(...$args, named: $extra);

Array unpacking with string keys

Array unpacking was added in PHP 7.4 but it couldn’t be used with string keys - now it can!

$arrayA = ['a' => 1];
$arrayB = ['b' => 2];

$result = [...$arrayA, ...$arrayB];

Objects as default parameters

Default parameter values can now initialize a class.

function foo(Bar $bar = new DefaultBar())
{
// etc
}
// equivalent to:
function foo(Bar $bar = null)
{
if ($bar === null)
$bar = new DefaultBar();

// etc
}

Final class constants

Class constants can be marked as final, meaning they cannot be overridden in child classes.

class Foo
{
final const BAZ = 'baz';
}
class Bar extends Foo
{
const BAZ = 'qux'; // error
}

Octal notation

A minor one to finish. PHP interprets 016 as an octal number (base 8), so this actually equals 14 in decimal. It now supports a more explicit syntax using 0o as a prefix, similarly to 0x for hexidecimal.

$fourteen = 0o16;

Full list of 8.1 features


PHP 8.0 #

Union types

Function/method parameters can declare multiple types using the pipe character |.

class Foo
{
public int|float $number;

public function bar(Collection|array $list)
{
// etc
}
}

Mixed type hint

Function/method arguments or return values can explicitly be declared as mixed type, which is equivalent to array|bool|callable|int|float|null|object|resource|string.

function foo(mixed $anything): mixed
{
if ($anything === 0)
return 0;

return 'not zero';
}

Trailing commas in function definitions

A comma can be used after the final argument in a function/method definition. Useful when there are many arguments split over multiple lines. Trailing commas in function calls were permitted as on PHP 7.3.

function foo(
SomeClass $longArgumentName,
AnotherClass $otherArgument, // comma now allowed
) {
// etc
}

Class resolution of variables

Previously only ClassName::class was possible, now it can be used on instance variables.

$object::class;

Named Arguments

Function/method parameters can be passed in any order using their names.

htmlspecialchars($string, double_encode: false);
// equivalent to:
htmlspecialchars($string, ENT_COMPAT|ENT_HTML401, 'UTF-8', false);

Catch exceptions without variable

The Exception variable is no longer required.

try {
// something that throws an exception
} catch (Exception) { // previously (Exception $ex)
exit;
}

Attributes

Attributes (aka annotations) can be added to properties and functions, and read from external code using Reflection.

#[MyAttribute("param")]
class Foo {}

class Bar
{
#[PlainAttribute]
public function qux() {}
}

// using attributes
$reflect = new ReflectionClass('Foo');
$attributes = $reflect->getAttributes();

Constructor property promotion

Syntactic sugar to set class properties in the constructor.

class Foo {
public function __construct(
public string $name,
private int $id
) {
// etc
}
}

// equivalent to:
class Foo {
public string $name;
private int $id;

public function __construct(
string $name,
int $id
) {
$this->name = $name;
$this->id = $id;
// etc
}
}

Nullsafe operator

Use ?-> to call methods and properties without needing to constantly check variable types.

$foo = $bar?->baz()?->qux;

// same as
$foo = null;
if ($bar instanceof ClassWithBaz) {
$a = $bar->baz();
$foo = $a->qux ?? null;
}

Static return type

Late static binding can be used as a return type.

class A
{
public function foo(): static
{
return new static;
}
}
class B extends A {}

(new A)->foo(); // returns A
(new B)->foo(); // returns B

Full list of 8.0 features


PHP 7.4 #

Typed properties

Type declarations on class member variables.

class Foo
{
public int $bar;
private string $qux;
}

Arrow functions

Shorthand syntax for anonymous functions; includes automatic variable binding (no need for ‘use’).

$foo = 3;
$multiplyFoo = fn($n) => $n * $foo;
// equivalent to:
$multiplyFoo = function($n) use ($foo) {
return $n * $foo;
}

Null coalesce assignment operator

Shortcut for setting a variable which may not exist yet.

$foo['bar'] ??= $defaultValue;
// equivalent to:
$foo['bar'] = $foo['bar'] ?? $defaultValue;

Array unpacking

The splat operator can be used inside arrays.

$foo = ['C', 'D'];
$bar = ['A', 'B', ...$foo, 'E'];

Number separator

Underscores can be added to numbers, and are ignored.

$oneMillion = 1_000_000;
// same as
$oneMillion = 1000000;

Full list of 7.4 features


PHP 7.3 #

Trailing commas in function calls

When calling a function or method, a trailing comma can be used, similar to arrays. Useful for long argument lists split onto multiple lines.

Note that trailing commas are still not allowed in function definitions prior to PHP 8.

myVeryLongFunctionName(
$myLongArgumentName,
$heresAnotherVariable, // comma now allowed
);

Better Heredoc/Nowdoc formatting

When using Heredoc or Nowdoc syntax, the string and closing identifier can now be indented, and the indentation will be stripped. In both examples here, $sql will be a three-line string with no indentation before each line.

It’s useful for multi-line strings such as SQL queries. The Heredoc syntax shown here parses variables just like double-quoted strings. Nowdoc syntax, which instead uses <<<'SQL' to start, does not parse the variables just like single-quotes strings.

// PHP 7.3+ Heredoc syntax
function foo()
{
$sql = <<<SQL
SELECT * FROM foobar
WHERE qux=1
ORDER BY name
SQL;
}
// PHP 7.2 Heredoc syntax
function foo()
{
$sql = <<<SQL
SELECT * FROM foobar
WHERE qux=1
ORDER BY name
SQL;

}

Full list of 7.3 features


PHP 7.2 #

Object type keyword

Allows generic object as a parameter/return type hint.

function foo(object $bar)
{
// etc
}

Parameter type widening

Overridden methods in extended classes or implemented interfaces may widen the parameter type hint (or remove it).

class General {}
class Specific extends General {}

class A
{
public function foo(Specific $abc)
{
// $abc must be of type Specific
}
}
class B extends A
{
public function foo(General $abc)
{
// $abc may be any General class, including Specific
// could remove type hint entirely
}
}

Trailing comma for namespace groups

A final comma can be used in grouped namespaces, similar to arrays.

namespace Foo\{
Bar,
Qux, // comma now allowed
}

Full list of 7.2 features


PHP 7.1 #

Nullable types

Parameter declarations and return types can optionally be null by adding a question mark to the type hint.

function foo(?int $input): ?string
{
if ($input === null)
return null;

return $input . 'foo';
}

Void return type

A void function must not return a value (including null).

function foo(): void
{
return;
}

Iterable type

A type hint specifying an array or an object that implements the Traversable interface.

function foo(iterable $iter)
{
foreach ($iter as $elem) {
//
}
}

Class constant visibility

A const in classes can be public, private or protected.

class Foo
{
public const BAR = 1;
private const QUX = 2;
}

Array destructuring

Use the short array syntax to save array values to separate variables.

$array = ['foo', 123];
[$str, $num] = $array;
// equivalent to
list($str, $num) = $array;

Array destructuring with keys

The list() construct can now specify which keys of an associative array to extract. Also works with short array syntax as above.

$array = ['id' => 123, 'name' => 'Foo'];
list('name' => $name, 'id' => $id) = $array;
// or
['name' => $name, 'id' => $id] = $array;

Negative string offset

Use square brackets to reference a specific character in a string, seeking backwards from the end.

$str = 'foobar';
$a = $str[-2]; // 'a'

Full list of 7.1 features


PHP 7.0 #

Uniform variable syntax

Changes to variable semantics including nested operators and operations on any expression in parentheses.

$foo()['bar']();
$foo::$bar::$baz;

// (...) is something that returns an array with key 'foo'
(...)['foo'];
// (...) is something that returns an object
(...)->bar();

// immediately-invoked function expression
(function() { ... })();

Scalar type hints

Use primitive types for function type hints: string, int, float, bool.

function foo(int $num, string $text)
{
// $num and $text are guaranteed to be an integer and string respectively
}

Return types

Declare that a function will return a specific type or class.

function foo(): string
{
return 'bar';
}

Null coalesce operator

Check a potentially null variable without generating warnings.

$foo = $array['bar'] ?? 'qux';
// equivalent to
$foo = isset($array['bar']) ? $array['bar'] : 'qux';

Spaceship operator

Operator that returns -1, 0 or 1. For use in sorting/comparison functions.

usort($array, function($a, $b) {
return $a <=> $b;
};

Anonymous classes

Create temporary objects to save writing a whole class. Can be useful to make quick objects implementing a simple interface, to pass into other functions.

$obj = new class {
function foo() { return 1; }
};

$num = $obj->foo();

Namespace groups

Use multiple namespaces that have similar paths, in one line.

use Foo\{Bar, Qux};
// equivalent to
use Foo\Bar;
use Foo\Qux;

Array constants

Arrays can be defined as constants.

define('PRIMES', [2, 3, 5, 7]);

Full list of 7.0 features


PHP 5.x #

Here’s a quick summary of features in older PHP versions.

Version Features
PHP 5.6 Splat operator (...), exponentiation operator ($a**2), use function
PHP 5.5 Generators, ::class, finally for try/catch
PHP 5.4 Short array syntax, traits, short echo tag always available
PHP 5.3 Namespaces, closures, shorthand ternary operator, goto