Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

register_shutdown_function overwrite

Tags:

function

php

Is it possible to overwrite the already set register_shutdown_function stack? Something like:

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 only call f2(). Is this possible?

like image 658
Eduard Luca Avatar asked Feb 24 '12 13:02

Eduard Luca


3 Answers

You can't do it straight, but there's 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);

Output:

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

The 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;
        }
}
like image 109
sanmai Avatar answered Sep 28 '22 19:09

sanmai


This is not possible. PHP has a remove_user_shutdown_function PHPAPI function, but this is not exposed to userland code.

like image 30
NikiC Avatar answered Sep 28 '22 19:09

NikiC


from the php doc page on register_shutdown_function():

Multiple calls to register_shutdown_function() can be made, and each will be called in the same order as they were registered. If you call exit() within one registered shutdown function, processing will stop completely and no other registered shutdown functions will be called.

so this means that if you want to only call function f2 you can pass it in to an exit() call in an exception handler. Multiple calls to register_shutdown_function() will call all of the functions in order, not just the last registered. Since there doesn't seem to be any sort of unregister_shutdown_function() this is what I suggest.

like image 27
Scott M. Avatar answered Sep 28 '22 18:09

Scott M.