With each new iteration of PHP comes new features for developers to play with, and PHP 8.1 is no different. PHP 8.1 brings a wealth of new features, including readonly properties, fibers, enums, intersection types, and more. This major update of PHP also included a new return type, 'never', which allows developers to set functions or methods as non-returning, in other words, will not return a value. We'll explore how this new return type works in PHP along with code examples to show it in action.
What does the return type never do?
The idea behind the never return type is to set functions or methods that will not return a value when called. That, therefore, means that if you were to call these types of functions, the PHP execution will either end or throw an exception (or similar). At first, it might appear strange why you'd actively want to end PHP script execution, but when you dig deeper, you'll see it becomes useful, especially when using static analysis tools or when working within your PHP IDE (integrated development environment) such as PhpStorm or Visual Studio. Other commonly interpreted programming languages such as TypeScript and Python already use this type of return type in their code bases.
As you develop PHP software there will be times when you'll create functions within your code base that don't actually return anything and don't continue the script execution past a particular point. This might appear similar to what the pre-existing return type 'void' does, but with the void return type, the function is one that might set class properties but still be required to execute the rest of a script. A good example of this is when we use setters and getters in an OOP class. In the example below, we're setting the property 'test', with the value '123'. Here we don't want the script to end here, we want it to continue, but as we're only setting a property, we don't expect the function to return anything, therefore we would use 'void'.
class foo
{
public $test;
public function setTest($test): void {
$this->test = $test;
}
}
$foo = new foo();
$foo->setTest('123');
However, this is different in the case of the 'never' return type. Let's take the below example. When calling our "endScript" function in the class 'foo', this would terminate the script because inside is a die function call. Because the function has the 'never' return type we know that, nothing else in the class will be executed.
class foo
{
public function endScript(): never {
die();
}
}
$foo = new foo();
$foo->endScript();
Examples of 'never' return type in PHP
One clear example of using the never return type is directing a user to a different page (location), with the PHP header function. Once the script gets to this point, we know that regardless if the function was set with the never return type, nothing else would get executed. The example below calls the "redirectUser" function that has a return type of never, meaning that the subsequent echo statement at the bottom "Welcome", will never get executed. Therefore, it'll be likely your static analysis tools (such as PHPStan or Psalm), or IDE will flag this line as unnecessary and request you to edit the class or remove the line completely.
class foo
{
public function redirectUser(): never {
header('Location: /dashboard');
die();
}
}
$foo = new foo();
$foo->redirectUser();
# This will never get executed
echo 'Welcome';
Let's adjust the code and move the echo statement into one of the class's own functions. Now, because we're calling another function that's got the never return type, the echo statement (like the example above) won't get called.
class foo
{
public function redirectUser(): never {
header('Location: /dashboard');
die();
}
public function processRequest(): never {
$this->redirectUser();
# This will never get executed
echo 'Welcome';
}
}
$foo = new foo();
$foo->processRequest();
You can use the never return type with either exit (which is equivalent to die), trigger_error, or anything that terminates the end of a PHP script. If inside a never return type function, you attempt to return something, PHP will trigger a fatal error, saying that "A never-returning function must not return". This is because PHP knows a developer attempting to return something from a never function is likely going to cause an unintended issue (bug).
class foo
{
public function bar(): never {
return 'this is a bad idea';
}
}
$foo = new foo();
// Calling this triggers a fatal error
$foo->bar();
Conclusion
Using the never return type is the best way to ensure your IDE and static analytics tools understand why a particular function has or will terminate a given PHP script. Using this return type should therefore be the last (bottom) type.
- For any function that terminates a PHP script, add the return type: never
- This replaces the need to add doc blocks or custom PHP 8 attributes
- Remember any code underneath a never return type will not be called
- For more PHP 8 functions, try str_contains