Что никогда не бывает возвращаемым типом в PHP 8.1
PHP 8.1 вводит тип возвращаемого значения, что это такое? и в чем разница между
never
и
void
?
2 ответа
Объявление типа введено для использования в качестве подсказки типа возвращаемого значения для функций, которые никогда не имеют ни неявных, ни явных операторов. И должен быть прекращен путем выдачи исключения или выхода с использованием
exit/die
функции.
function redirect(string $uri): never
{
header('Location: ' . $uri);
exit();
}
Здесь
redirect
называется никогда не возвращающейся функцией, потому что:
1) Он не имеет явно определенного оператора.
function redirect(string $uri): never
{
exit();
return 'something';
}
Продовольствие:
Неустранимая ошибка PHP: никогда не возвращающаяся функция не должна возвращать
2) Не имеет
return
заявление определено неявно.
function redirect(string $uri): never
{
if (false) {
header('Location: ' . $uri);
exit();
}
}
Поскольку условие здесь никогда не выполняется, выполнение перескакивает через оператор if и возвращается неявное
NULL
что приведет к:
Неустранимая ошибка PHP: Uncaught TypeError: redirect(): никогда не возвращающаяся функция не должна неявно возвращать
3) Завершает выполнение
exit
функция
Пустота против никогда
- может иметь
return;
но не могу. - принудительно запускает функцию или завершает ее с помощью exit / die, но этого не происходит.
- является подтипом любого другого типа в системе типов PHP, включая void (это позволяет ковариантность возвращаемого типа).
- Оба не позволяют возвращать значение.
- И то, и другое нельзя использовать в качестве параметра или типа свойства.
- Оба могут использоваться только как отдельный тип (объединение или пересечение недопустимо).
Когда выбирать, и наоборот?
Вы должны объявить тип возвращаемого значения функции
void
когда вы ожидаете, что PHP выполнит следующий оператор после вызова функции. И ты должен это объявить
never
когда не ожидаете, что PHP выполнит следующий оператор после этого вызова функции.
С помощью (PHP 8.1) вы можете защитить функцию, чтобы она никогда не возвращалась, например, если вы хотите убедиться, что созданный бесконечный цикл действительно будет бесконечным (с точки зрения места вызова):
<?php
function eternity(string $forEternity): never
{
start:
usleep(1000);
goto start;
}
eternity('the future');
// <- we are here only after the next big-bang, not in this current universe.
Этот код очень упрощен, обычно забывание инструкции goto вызывает ошибку.
Бесконечные циклы обычно также не нужны для защиты ( поскольку обычно мы никогда не хотим, чтобы они происходили), но полезно, чтобы функция
die()
,
exit()
или же
throw
Исключение, всегда.
Опять же, хотя эти три способа выхода из функции не рекомендуются в стандартном потоке управления (первые два даже контролируют запущенный процесс в некоторых SAPI). Но, наконец (без каламбура), можно сделать так, чтобы IDE и инструментарий видели, что функция никогда не возвращает прямо из информации о типе возвращаемого значения, закодированной в коде. Это также включает людей, которые используют такие инструменты или читают код.
С (PHP 7.1) вы гарантируете, что функция никогда не вернет тип, включая нижний тип (поскольку вы можете использовать только
void
или же
never
).
<?php
function back_from_eternity(string $forEternity): void
{
usleep(100000); // not so long
return $forEternity
}
$echo = back_from_eternity('soon');
Позволяет PHP предотвращать возврат эха из вечности, а также читателю замечать, что
$echo =
(и все, что потом делается с этой переменной) по-прежнему требует обычного обслуживания/отладки/тестирования или разработки.
- Сравните: Void как возвращаемый тип
У обоих есть то преимущество, что они выбрасывают, когда они нарушаются, поэтому программа никогда не будет продолжаться как есть и отобразит вызов функции, возвращающий недействительным (все предназначенные каламбуры).
Следует учитывать любые побочные эффекты от вызова функции. Обычно это про них.