Можно ли перезаписать уже установленный стек register_shutdown_function
? Что-то вроде:
function f1(){ echo "f1"; } function f2(){ echo "f2"; } register_shutdown_function("f1"); echo "actions here"; register_shutdown_function("f2"); call_to_undefined_function(); // to "produce" the error
В этом случае я хочу, чтобы скрипт вызывал только f2()
. Это возможно?
Это невозможно. PHP имеет функцию remove_user_shutdown_function
PHPAPI, но это не распространяется на код пользователя.
Вы не можете сделать это прямо, но всегда есть обходное решение:
$first = register_cancellable_shutdown_function(function () { echo "This function is never called\n"; }); $second = register_cancellable_shutdown_function(function () { echo "This function is going to be called\n"; }); cancel_shutdown_function($first);
Вывод:
$ php test.php This function is going to be called
Код :
function register_cancellable_shutdown_function($callback) { return new cancellable_shutdown_function_envelope($callback); } function cancel_shutdown_function($envelope) { $envelope->cancel(); } final class cancellable_shutdown_function_envelope { private $callback; public function __construct($callback) { $this->callback = $callback; register_shutdown_function(function () { $this->callback && call_user_func($this->callback); }); } public function cancel() { $this->callback = false; } }
с страницы php doc на register_shutdown_function()
:
Можно сделать несколько вызовов register_shutdown_function (), и каждый будет вызываться в том же порядке, в каком они были зарегистрированы. Если вы вызываете exit () в пределах одной зарегистрированной функции выключения, обработка полностью прекратится, и никакие другие зарегистрированные функции выключения не будут вызваны.
поэтому это означает, что если вы хотите только вызвать функцию f2
вы можете передать ее вызову exit () в обработчике исключений. Несколько вызовов register_shutdown_function()
вызовут все функции в порядке, а не только последние зарегистрированные. Поскольку, похоже, не существует какой-либо unregister_shutdown_function()
это то, что я предлагаю.
Другой вариант – использовать следующую функцию:
function register_named_shutdown_function($name, $callback) { static $callbacks = []; $callbacks[$name] = $callback; static $registered; $registered || $registered = register_shutdown_function(function () use (&$callbacks) { array_map(function ($callback) { call_user_func($callback); }, $callbacks); }) || true; }
Использование образца:
register_named_shutdown_function("first", function () { echo "Never executed\n"; }); register_named_shutdown_function("second", function () { echo "Secondly executed\n"; }); register_named_shutdown_function("first", function () { echo "Firstly executed\n"; });
Выходы:
Firstly executed Secondly executed
У меня тоже есть эта проблема, и я решил это как:
function f1(){ if (defined('CALL1') && CALL1===false) return false; echo "f1"; } function f2(){ echo "f2"; } register_shutdown_function("f1"); echo "actions here"; define('CALL1', false); register_shutdown_function("f2"); call_to_undefined_function();