Что никогда не бывает возвращаемым типом в 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 = (и все, что потом делается с этой переменной) по-прежнему требует обычного обслуживания/отладки/тестирования или разработки.


У обоих есть то преимущество, что они выбрасывают, когда они нарушаются, поэтому программа никогда не будет продолжаться как есть и отобразит вызов функции, возвращающий недействительным (все предназначенные каламбуры).

Следует учитывать любые побочные эффекты от вызова функции. Обычно это про них.

Другие вопросы по тегам