Introduction
There may be times when you're writing a function in PHP that you know will never return a value. This could be because the function always throws an exception, or maybe calls exit
or die
. In these cases, you might want to use the never
type.
Admittedly, the never
type isn't something I reach for very often, but it's useful in certain scenarios, especially when you want to make it clear to other developers that a function will not return normally.
In this article, we're going to explore the never
type in PHP, how to use it, and some practical examples. I'll also include a cheat sheet at the end of this article that you can refer back to.
How to Use "never" in PHP
The never
type was introduced in PHP 8.1 (released: November 2021) and is used to indicate that a function will never return. This signals to PHP, and other developers reading the code, that the function is not expected to return a value under any circumstances. This could be due to the function throwing an exception, or maybe calling something like exit
or die
.
The never
type can only be used as a return type, and cannot be used as a parameter type.
Let's take a look at a quick example of how to use the never
type in PHP:
1public function doSomething(): never2{3 throw new Exception('Exception message here.');4}
As we can see in the example above, the doSomething
function uses the never
return type because it will always throw an exception.
Let's change our example and update the doSomething
function to return a value instead of throwing an exception. We're doing this to purposely break the code and show how PHP handles it:
1public function doSomething(): never2{3 return 'This will cause an error';4}
In our code example above, we are trying to return a string while using the never
return type. This will result in a fatal error being thrown by PHP with the following message:
1Fatal error: A never-returning function must not return in /in/32Ts2 on line 3
Implicit Returns with "never"
If a function is declared with a never
return type, isn't able to implicitly return a value. Doing so will also result in a fatal error.
For example, let's imagine we have a method that is used to publish a blog post:
1namespace App\Services; 2 3use App\Enums\ArticleStatus; 4use App\Models\Article; 5 6class ArticleService 7{ 8 public function publishArticle(Article $article): never 9 {10 $article->published_at = now();11 $article->status = ArticleStatus::Published;12 13 $article->save();14 }15}
As we can see in the example above, the publishArticle
method doesn't exit from the function or throw an exception. It also doesn't explicitly return a value. As a result, this means it will implicitly return and PHP will throw a fatal error when we try to call this method:
1Fatal error: Uncaught TypeError: ArticleService::publishArticle(): never-returning function must not implicitly return
Using "never" with Intersection Types
The never
type cannot be used in PHP as part of an intersection type.
For example, let's take the following code snippet:
1public function doSomething(): never&string2{3 throw new Exception('This will cause an error');4}
Running this would result in a fatal error with the following message:
1Fatal error: Type never cannot be part of an intersection type
Using "never" with Union Types
The never
type cannot be used in PHP as part of a union type.
For example, let's take the following code snippet:
1public function doSomething(): never|string2{3 throw new Exception('This will cause an error');4}
Running this would result in a fatal error with the following message:
1Fatal error: never can only be used as a standalone type
Example Use Case
Now that we've covered the basics of the never
type, let's take a look at a practical example of how it can be used in a real-world scenario.
If you've used Laravel or Symfony before, you'll likely be familiar with the dd
(dump and die) function. This function is used to dump variables and stop the script execution. It can be quite a handy tool for debugging to quickly inspect variables and see their contents.
This functionality is made available via the symfony/var-dumper
package. Let's take a look at how the never
type is used in the dd
function (https://github.com/symfony/var-dumper/blob/7.3/Resources/functions/dump.php):
1if (!function_exists('dd')) { 2 function dd(mixed ...$vars): never 3 { 4 if (!in_array(\PHP_SAPI, ['cli', 'phpdbg', 'embed'], true) && !headers_sent()) { 5 header('HTTP/1.1 500 Internal Server Error'); 6 } 7 8 if (!$vars) { 9 VarDumper::dump(new ScalarStub('๐'));10 11 exit(1);12 }13 14 if (array_key_exists(0, $vars) && 1 === count($vars)) {15 VarDumper::dump($vars[0]);16 } else {17 foreach ($vars as $k => $v) {18 VarDumper::dump($v, is_int($k) ? 1 + $k : $k);19 }20 }21 22 exit(1);23 }24}
Now, we don't need to fully understand the entire implementation of the dd
function, but we can see that there are only two places where the function will finish running. Both of these places use exit(1)
, which means the script will terminate at that point. This is a perfect example of a function that will never return a value, and thus it is declared with the never
return type.
Cheat Sheet
The never
type in PHP:
- Is used to indicate that a function will never return.
- Can only be used as a return type.
- Cannot be used as a parameter type.
- Cannot be used in intersection types.
- Cannot be used in union types.
- Is available since PHP 8.1.
Conclusion
In this article, we've explored the never
type in PHP, how to use it, and a practical example of how it's used in the symfony/var-dumper
package's dd
function. Hopefully, you should now feel confident using the never
type in your own PHP code.
If you enjoyed reading this post, you might be interested in checking out my 220+ page ebook "Battle Ready Laravel" which covers similar topics in more depth.
Or, you might want to check out my other 440+ page ebook "Consuming APIs in Laravel" which teaches you how to use Laravel to consume APIs from other services.
If you're interested in getting updated each time I publish a new post, feel free to sign up for my newsletter below.
Keep on building awesome stuff! ๐