PHP 8: Key Changes and Features
If you stopped paying attention to PHP updates after 2012, you’d be forgiven for thinking that PHP is dead. However, PHP is alive and kicking, having undergone several vital improvements since 2012 with the introduction of PHP 5.4. Don’t believe it? Let’s look at some of the many language changes that PHP has undergone, right up to PHP 8.
Traits:
PHP 5.4 brought an end to the monotonous rewriting of the same method body or abusing inheritance by introducing Traits, which favor composition over inheritance. In layman’s terms, Traits are chunks of code that you can use in different classes without having to duplicate the code or inherit classes.
Old way:
class Foo{
public function log($msg){
//log message
}
}
class Bar{
public function log($msg){
//log message
}
}
New way:
trait Logger{
public function log($msg){
//log message
}
}
class Foo{
use Logger;
}
class Bar{
use Logger;
}
Short Array Syntax:
In PHP 5.4, no more writing out ‘array’ like a caveman; you can simply use square brackets for an array.
$names = array('Jeffrey', 'John', 'Mary'); // Old way
$names = ['Jeffrey', 'John', 'Mary']; // New way
Array Destructuring:
Instead of assigning an array to a temporary variable to define multiple variables, now, you can use array destructuring.
$array = array('a', 'b', 'c');
$a = $names[0];
$b = $names[1];
$c = $names[2];
// turns into this
$array = array('a', 'b', 'c');
[$a, $b, $c] = $names;
First-class Variadic Functions
With PHP 8, it’s possible to make use of first-class variadic functions, allowing you to pass as many arguments to a function as you might need, using the ‘…’ operator.
function sum(...$numbers){
return array_sum($numbers);
}
echo sum(1, 2, 3, 4); // Outputs 10
Arrow Functions
Those familiar with JavaScript will feel at home with PHP 8’s introduction of arrow functions. These functions make use of the ‘fn’ keyword to define a new function in a more compact and readable format.
Old way:
array_map(function($item){
return $item->id;
}, $items);
New way:
array_map(fn($item) => $item->id, $items);
Null Coalescing Operator
PHP 7 first gave us the null coalescing operator, allowing for more concise and readable code. This operator returns its first operand if it exists and is not null; otherwise, it returns its second operand.
$username = $_GET['user'] ?? 'nobody';
PHP 7.4 further improved this by bringing the null coalescing assignment operator ‘??=’. This operator will leave the variable as-is if it’s already set; otherwise, it will assign the given value.
$_GET['user'] ??= 'nobody';
Null Chaining Operator
The null chaining operator introduced in PHP 8 has significant improvements in operating with objects and properties. It will stop the chain and return null if a null value is encountered.
Old way:
$age = $user->age;
$age = $age ? $age->format('Y-m-d') : null;
New way:
$age = $user->age?->format('Y-m-d');
Named Arguments
Named arguments give you the freedom to skip optional parameters without the need to insert a null value, keeping your function calls cleaner and more self-documented.
Old way:
function createOrder($user, $product, $quantity = null, $price){
//create order
}
createOrder($user, $product, null, 100);
New way:
function createOrder($user, $product, $quantity = null, $price){
//create order
}
createOrder(
user: $user,
product: $product,
price: 100,
);
Weak Maps
A new data structure was added to PHP 8 called Weak Maps for objects that will get garbage collected when there are no more references to that object. This is a fantastic memory-saving tool.
class Foo{
protected WeakMap $cache;
public function get($key){
return $this->cache[$key] ?? null;
}
}
Enums
Enums provide a way to define a set of named values with corresponding constants. PHP 8 introduces native enums, allowing you to define your own enumerated types with fewer chances of errors.
enum Status: int
{
case DRAFT = 1;
case PUBLISHED = 2;
case ARCHIVED = 3;
//friendly display
public function display(): string
{
return match ($this) {
self::DRAFT => 'Draft',
self::PUBLISHED => 'Published',
self::ARCHIVED => 'Archived',
};
}
}
Typed Properties
With PHP 7.4 came the ability to specify types for class properties, ensuring better code quality and eliminating potential errors. PHP 8 builds upon this feature to provide more concise syntax and additional read-only properties.
Old way:
class Foo{
public string $title;
public DateTime $date;
public function __construct(string $title, DateTime $date){
$this->title = $title;
$this->date = $date;
}
}
New way:
class Foo{
public function __construct(
public string $title,
public readonly DateTime $date,
){}
}
Match Statement (switch)
The match statement is an enhanced version of the switch statement, providing more expressive syntax and making switch statements cleaner and more readable.
Old way:
switch($status){
case 200:
$message = 'OK';
break;
case 300:
$message = 'Multiple Choices';
break;
case 400:
$message = 'Bad Request';
break;
case 500:
$message = 'Internal Server Error';
break;
}
New way:
$message = match($status){
200 => 'OK',
300 => 'Multiple Choices',
400 => 'Bad Request',
500 => 'Internal Server Error',
default => 'Unknown Status',
};
Type Hints and Type Declarations
Type hints and type declarations are a significant addition to PHP, enabling you to specify the expected parameter and return types for functions and methods. This enhances code clarity and offers better validation during development.
class Foo{
public function setStatus(Status $status){
//
}
}
PHP 7 and PHP 8 have made significant strides in terms of type safety, allowing developers to add type hints to function arguments, return values, and class properties. This helps catch potential type-related errors during development and improves code reliability.
Typed Arguments and Return Types
In previous versions of PHP, function arguments and return types were not explicitly defined. However, PHP 7 introduced the ability to specify the expected types for function arguments and return values.
function add(int $a, int $b): int {
return $a + $b;
}
In this example, the add function expects two integer arguments ($a and $b) and returns an integer.
Union Types
PHP 8 introduced union types, which allow you to specify that a parameter or return value can be of more than one type. This is useful when a variable can hold different types of values.
function sum(int|float ...$numbers): int|float {
return array_sum($numbers);
}
In this example, the sum function can accept either int or float values as variable arguments and can return either an int or float.
Intersection Types
Intersection types, also introduced in PHP 8, allow you to specify that a parameter or return value must adhere to multiple types simultaneously. This is useful when you want to ensure that an object implements multiple interfaces, for example.
public function someMethod(Foo & Bar $input): void {
// Code here
}
In this example, the $input parameter must be an object that implements both the Foo and Bar interfaces.
Nullable Types
Nullable types allow you to specify that a parameter or return value can be either of a specified type or null.
function setAge(?int $age): void {
// Code here
}
In this example, the setAge function expects an optional int parameter but also allows null values.
Read-only Properties
PHP 8 introduced a new readonly modifier for class properties, allowing you to specify that a property can only be initialized once and cannot be modified after that.
class Foo {
public function __construct(public readonly string $name) {}
}
In this example, the name property is marked as read-only, indicating that it can only be assigned a value during object construction but cannot be modified later.
Performance Improvements
One common misconception is that PHP is slow. However, PHP has undergone significant performance improvements in recent years, making it capable of handling most use cases efficiently.
Between PHP 5.6 and PHP 7, there was nearly a 400% performance increase, and PHP 8 brought additional performance enhancements, improving speed by about 20%.
While PHP might not be suitable for extremely high-performance scenarios with tens of thousands of requests per second, it is fast enough for the majority of web development needs. For specialized use cases with high-performance requirements, there are other specialized languages available.
Conclusion
PHP has evolved significantly since 2012, with the introduction of numerous features and improvements in PHP 5.4, PHP 7, and PHP 8. Traits, short array syntax, array destructuring, variadic functions, arrow functions, null coalescing operators, named arguments, and improved switch statements are just some of the many enhancements brought to the language. Additionally, PHP has seen improvements in type safety, allowing developers to create more reliable and robust code. With performance advancements, PHP is faster than ever before.
Therefore, it is safe to say that PHP is not dead. It remains a popular and relevant programming language, constantly evolving to meet the demands of modern web development.

