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;
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;
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
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;
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;
}
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
}
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'
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]);
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 |