Register_shutdown_function rewrite

Can I overwrite an already installed stack register_shutdown_function? Sort of:

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

In this case, I want the script to call only f2(). Is it possible?

+5
source share
5 answers

It's impossible. PHP has remove_user_shutdown_functiona PHPAPI function, but this does not apply to userland code.

+3
source

You cannot do this directly, but there is always a workaround:

$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);

Conclusion:

$ php test.php
This function is going to be called

Code :

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;
        }
}
+3
source

php doc register_shutdown_function():

register_shutdown_function(), , . exit() , .

therefore, this means that if you only want to call the function f2, you can pass it to the exit () call in the exception handler. Several calls to register_shutdown_function()will call all the functions in order, not just the last registered ones. Since there does not seem to be any unregister_shutdown_function(), this is what I suggest.

+2
source

Another option is to use the following 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;
}

Sample Usage:

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";
});

Outputs:

Firstly executed
Secondly executed
+1
source

I have this problem too, and I solved it as:

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();
0
source

All Articles