note 104062 deleted from function.register-shutdown-function by danbrown
| From: | danbrown@php.net | Date: | Fri, 20 May 2011 14:28:47 +0000 |
| Subject: | note 104062 deleted from function.register-shutdown-function by danbrown | ||
| References: | 1 | Groups: | php.notes |
| Request: | Send a blank email to php-notes+get-179909@lists.php.net to get a copy of this message | ||
Note Submitter: dcz at phpbb-seo dot com
----
I found that emanueledelgrande's shutdownScheduler class was quite a nice approach.
Here another version of the same concept with a priority feature. I also though that turning it to
static would be more appropriate, and also handier to use (it can be used anywhere without global or
get instance this way).
<?php
/**
* shutdown
* Author : dcz
* inspired from emanueledelgrande's shutdownScheduler : http://www.php.net/register_shutdown_function#100000
* Feel free to use as you wish at your own risk ;-)
**/
class shutdown {
private static $callbacks = array();
private static $priorities = array();
private static $inited = false;
/**
* void init()
**/
private static function init() {
if (!self::$inited) {
self::$inited = true;
register_shutdown_function('shutdown::call');
}
}
/**
* void set_priotity(string $key, int $priority)
**/
public static function set_priotity($key, $priority) {
self::$priorities[(string) $key] = (int) $priority;
}
/**
* bool is_registered(string $key)
**/
public static function is_registered($key) {
return isset(self::$callbacks[$key]);
}
/**
* bool register()
**/
public static function register() {
if (!self::$inited) {
self::init();
}
$callback = func_get_args();
if (empty($callback)) {
return false;
}
if (!is_callable($callback[0])) {
return false;
}
if (is_array($callback[0])) {
$key = get_class($callback[0][0]) . '->' . $callback[0][1];
} else {
$key = $callback[0];
}
self::$callbacks[$key] = $callback;
return true;
}
/**
* void call()
**/
public static function call() {
$_callbacks = array();
foreach (self::$callbacks as $key => & $arguments) {
if (isset(self::$priorities[$key])) {
$_callbacks[self::$priorities[$key]][$key] = & $arguments;
} else {
$_callbacks[0][$key] = & $arguments;
}
}
krsort($_callbacks);
foreach ($_callbacks as $priority => & $calls) {
foreach ($calls as $key => & $args) {
$callback = array_shift($args);
call_user_func_array($callback, $args);
}
}
}
}
?>
Usage :
<?php
class statictest {
public static function test($str) {
echo $str . '<br/>';
}
public static function test2($str) {
echo $str . '<br/>';
}
}
class objtest {
function __construct() {
shutdown::register(array(&$this, 'test3'), 'Calling objtest->test3');
}
public function test($str) {
echo $str . '<br/>';
}
public function test2($str) {
echo $str . '<br/>';
}
public function test3($str) {
echo $str . '<br/>';
}
}
function test($str) {
echo $str . '<br/>';
}
function test2($str) {
echo $str . '<br/>';
}
$obj = new objtest(); // will register our first "event"
// regular registering, registered events triggered in the order they where created
// you could want to test the result to know if the registration actually went through
shutdown::register('statictest::test', 'Calling statictest::test');
shutdown::register('statictest::test2', 'Calling statictest::test2');
shutdown::register(array(&$obj, 'test'), 'Calling objtest->test');
shutdown::register(array(&$obj, 'test2'), 'Calling objtest->test2');
shutdown::register('test', 'Calling test');
shutdown::register('test2', 'Calling test2');
// we can overwrite
shutdown::register(array(&$obj, 'test'), 'Overwritten objtest->test call,
original trigger order kept');
// we can also make sure we do not overwrite if necessary
if (!shutdown::is_registered('test2')) {
shutdown::register('test2', 'Overwrite test2 call if not already registered');
}
// set some priorities, keys are using original notation for class names (from get_class in php5),
// chosen convention should be obvious to understand
// greatest priority will be triggered first
shutdown::set_priotity('statictest::test2', 10);
shutdown::set_priotity('objtest->test2', 10);
shutdown::set_priotity('test2', 11);
shutdown::set_priotity('statictest::test', -10);
exit;
?>
Would display :
Calling test2
Calling statictest::test2
Calling objtest->test2
Calling objtest->test3
Overwritten objtest->test call, original trigger order kept
Calling test
Calling statictest::test