Four Modern PHP Features That Show How Far the Language Has Come

by | Apr 8, 2026

PHP has evolved over the years and has become a lot reliable, faster and refined. And with the release of PHP 8, which contained many features (named arguments, union types, attributes, constructor property promotion, match expressions, the null safe operator (?->) etc) and optimizations (JIT compiler), PHP has become more faster and cleaner. There are many more improvements and interesting features in the later versions of PHP 8.

The 4 features I now rely on and wish PHP had introduced much earlier:

1. Named arguments

Before PHP 8, calling a function with optional parameters required passing all preceding arguments, even ones you didn’t need. For example, if a function had two optional parameters and you only wanted to use the second one, you still had to explicitly provide a value for the first.
PHP 8 introduced named arguments, which allow you to pass values to a function by parameter name rather than position. This means you can skip optional parameters you don’t need and only provide the ones that matter — resulting in cleaner, more readable, and less error-prone code.

Example:
function sendBirthdayGreetings(string $name, string $message = 'Happy Birthday', string $specialMessage = '')
{
    $message .= " $name!";
    if ($specialMessage === '') {
        return $message;
    }
        
    return $message . "\n$specialMessage";
}
    
    
// Calling the function Before PHP 8 
echo sendBirthdayGreetings('John', 'Happy Birthday', 'May you have a prosperous ahead!');
    
// Calling the function after PHP 8
echo sendBirthdayGreetings('John', specialMessage: 'May you have a prosperous ahead!');

2. match expressions

The match expression is one of my favorite additions in PHP 8. Instead of writing long, if-elseif-else conditional blocks or switch statements with break calls, you can now use match to evaluate a value and execute the corresponding branch in a clean, concise way.

Important things to know before using match:

  • Strict comparison — match values strictly (===), unlike switch which performs loose check (==).
  • Returns a value — match always returns a value, which can then be assigned to a variable. You do not need to use the returned value if it is not necessary.
  • No accidental fall-through — in contrast to switch, match does not fall through to the subsequent cases.
  • Throws UnhandledMatchError on no match — if no arm matches and there is no default, PHP throws an UnhandledMatchError, preventing silent failures. In other words, match is exhaustive and requires all possibilities to be covered.
  • Multiple expressions per arm — you can write multiple expressions per arm separated by comma with the same right-hand side. This matches the arm against multiple conditions. It is similar to writing a logical OR.
Example:
// Before PHP 8 without match expression
$status = 'ok';
switch ($status) {
    case 'ok':
    case 'up':
        $color = 'green';
        break;
    case 'down':
    case 'critical':
        $color = 'red';
        break;
    case 'warning':
        $color = 'orange';
        break;
    case 'pending':
        $color = 'blue';
        break;
    case 'unknown':
        $color = 'purple';
        break;
    default:
        $color = 'gray';
}

    
    
// From PHP 8 with match expression
$color = match ($status) {
    'ok', 'up' => 'green',
    'down',
    'critical' => 'red',
    'warning' => 'orange',
    'pending' => 'blue',
    'unknown' => 'purple',
    default => 'gray',
};

 

3. Null safe operator

Since PHP 8, reading the properties of an object or calling its methods can be safely done through the newly introduced null safe operator (?->). There is no need to write an if condition to check whether the object is null before accessing it. If the object is null, the chain short circuits and returns null. The real advantage is that, you could chain several such calls.

Example:
// Before PHP 8 without null safe operator
  $city = null;
  if ($user !== null && $user->getAddress() !== null) {
      $city = $user->getAddress()->getCity();
  }

  // From PHP 8 with null safe operator
  $city = $user?->getAddress()?->getCity();

4. Constructor property promotion

Before PHP 8, properties used in a class constructor were also required to be declared before values could be assigned to them. Starting with PHP 8, constructor parameters can be promoted directly to object properties, which also eliminates the assignment step.
This means the steps of declaring properties and assigning them values in the constructor are eliminated.

Example:
Before PHP 8:
class User
{
    public $userName;
    
    public __constructor(string $name)
    {
        $this->userName = $name;
    }
}
From PHP 8:
class User
{    
    public __constructor (public string $name) {}
}

The main advantages of this feature are:

  • Reduced boilerplate code.
  • Elimination of mismatch between the property name and the constructor parameter names
  • Removal of constructor parameters is just one step (no need to search for unused properties after removing the parameter).
  • It also encourages property type declaration

Modern PHP has really come a long way and has become much more reliable and cleaner to write. This is largely thanks to the features covered in this post, along with further improvements in later releases. If you’re already using PHP or considering to use it, start using version 8.2+, to get the most out of it.

You May Also Like…

 

Icinga Director v1.11.6 Release

Icinga Director v1.11.6 Release

We are happy to announce the release of Icinga Director version 1.11.6. This release addresses several important bug...

Subscribe to our Newsletter

A monthly digest of the latest Icinga news, releases, articles and community topics.