PHP 8.4: exit/die изменены из языковых конструкций в функции

Источник: «PHP 8.4: exit/die changed from language constructs to functions»
Ключевое слово exit и его псевдоним die — языковые конструкции, выводящие сообщение и завершающие текущий сценарий. В CLI-приложениях exit/die можно использовать для завершения работы приложения с заданным кодом выхода.

Некоторые языковые конструкции, такие как require, include, echo и exit, работают аналогично функциям PHP, но у них есть собственные лексемы, функциональность, они необязательно имеют возвращаемые значения и необязательно должны вызываться с круглыми скобками.

Поскольку exit и die являются языковыми конструкциями, это позволило использовать различные способы их вызова. Они не требовали круглых скобок и принимали string или значение int, которые либо выводились в STDOUT (в случае string), либо использовались в качестве кода выхода (в случае int):

exit; // Допустимо
exit(); // Допустимо
exit(1); // Допустимо
exit("Fatal error, exiting"); // Допустимо

Необязательный параметр до версии PHP 8.4 принимал значение в виде string или int, но при этом не использовал жонглирование типами или строгую типизацию.

declare(strict_types=1);

exit([]);
// Warning: Array to string conversion in ... on line ...
// Array

В PHP 8.4 exit и die объявлены функциями PHP. Они имеют специальную обработку, позволяющую вызывать их без скобок, обеспечивая обратную совместимость со старыми приложениями PHP.

Синопсис функции exit и die

function exit(string|int $status = 0): never {}

function die(string|int $status = 0): never {}

Функция die эквивалентна функции exit. Обе функции объявлены в глобальном пространстве имён. Обе они возвращают тип never.

Без изменений: Вызов exit и die без круглых скобок

Для обеспечения обратной совместимости функции exit и die по-прежнему можно вызывать без круглых скобок. Такой вызов не вызывает никаких уведомлений об устаревании.

exit; // Допустимо
die; // Допустимо

Без изменений: exit и die нельзя отключить INI директивами disable_functions

Новые функции exit и die не могут быть отключены с помощью директивы disable_functions. При этом выдаётся предупреждение PHP, и функции остаются включёнными:

[PHP]
disable_functions=exit,die
Warning: Cannot disable function exit()
Warning: Cannot disable function die()

Без изменений: exit и die недоступны для имён функций, имён классов, имён const и меток goto

exit и die не могут служить именами функций или констант, даже внутри пространства имён. Кроме того, exit и die не могут быть использованы в качестве меток для goto.

Все следующие фрагменты приводят к синтаксической ошибке во всех версиях PHP, включая PHP 8.4 и более поздние.

function exit() {}

namespace Test;
function exit() {}

// Parse error: syntax error, unexpected token "exit", expecting "("
const die = 42;
const EXIT = 42;

// Parse error: syntax error, unexpected token "exit", expecting identifier

По-прежнему можно использовать define для объявления константы с именами exit и die. Однако обратите внимание, что попытка использовать константу приведёт к вызову die или exit, а не к получению значения константы.

exit:
echo "Called";

// Parse error: syntax error, unexpected token ":"

Без изменений: exit и die могут использоваться как члены Enum, константы класса, методы и свойства

exit и die могут использоваться в качестве имён констант класса, имён методов класса и имён свойств. Следующий фрагмент допустим во всех версиях PHP, включая PHP 8.4 и более поздние. Кроме того, поскольку Enum расширяют внутреннюю структуру классов PHP, exit и die также являются допустимыми именами членов Enum:

class Test {
public int $exit = 442;
public int $die = 116;

public const int exit = 42;
public const int die = 16;

public function exit() {
return self::exit;
}

public function die() {
return self::die;
}
}

$c = new Test();
echo $c->exit(); // 42
echo $c->die(); // 16
echo $c->exit; // 442
echo $c->die; // 116
echo Test::exit; // 42
echo Test::die; // 16

Изменения в обработке типов

Поскольку exit и die являются функциями PHP в PHP 8.4 и более поздних версиях, они теперь следуют стандартной обработке типов, которой следуют другие функции PHP.

ArgumentCountError на дополнительных параметрах

Ранее передача более одного параметра в exit/die приводила к синтаксической ошибке. В PHP 8.4 это вызывает исключение ArgumentCountError.

exit(255, "foobar");

// ArgumentCountError: exit() expects at most 1 argument, 2 given

Стандартное жонглирование типами вне strict_types

Подобно тому, как работают остальные функции PHP, exit и die теперь следуют тем же правилам жонглирования типами/согласования. Это влияет на обратную совместимость, но, возможно, в более правильном направлении.

Примечательно, что:

Исключения TypeError, при действующем strict_types

Когда используется strict_types=1, передача любого значения, отличного от string или int, вызывает исключение TypeError:

declare(strict_types=1);

exit(null);

//TypeError: exit(): Argument #1 ($status) must be of type string|int, null given

exit и die могут быть callable

Поскольку exit и die являются функциями PHP, их теперь можно использовать как стандартные PHP callable.

В PHP 8.3 и более ранних версиях следующие фрагменты не работают, потому что exit не объявлена как callable функция в этих версиях.

$callable = 'exit';
$status = "My success message";
$callable($status);
$callable = exit(...);
$status = "My success message";
$callable($status);

В этом примере используется синтаксис callable первого класса.

Влияние на обратную совместимость

exit и die теперь являются функциями PHP. Однако это изменение в значительной степени обратно совместимо со старыми версиями PHP, поскольку exit и die по-прежнему не могут использоваться в качестве имён классов, констант и функций, и по-прежнему могут использоваться в качестве имён констант, свойств и методов классов.

Использование exit и die в качестве callable поддерживается только в PHP 8.4 и более поздних версиях.

Поскольку exit и die являются языковыми конструкциями в более ранних версиях PHP, невозможно (да и не нужно) использовать полифилл для этих функций.

Комментарии


Дополнительные материалы

Предыдущая Статья

Испортили git rebase?

Следующая Статья

Новое в Symfony 7.2: Упрощение настройки доверенных прокси