note 96021 deleted from function.get-called-class by danbrown

From: Date: Wed, 03 Feb 2010 16:43:38 +0000
Subject: note 96021 deleted from function.get-called-class by danbrown
References: 1  Groups: php.notes 
Request: Send a blank email to php-notes+get-165629@lists.php.net to get a copy of this message
Note Submitter: feb2010 at birth-online dot de ---- The get_called_class() implementation of "laurence+nospam at sol1 dot com dot au" further down doesn't know anything if you called a static method from within another static method using call_user_func() or call_user_func_array(). In this case, the second backtrace entry ($l=1) has no "file" or "line" and the lookup fails. I added a few lines to look further in the backtrace for these two cases and get the class name from the first parameter of call_user_func/call_user_func_array. This is what the function looks like for now: <?php /******************************** * Retro-support of get_called_class() * Tested and works in PHP 5.2.4 * http://www.sol1.com.au/ * additions by Markus Birth <feb2010@birth-online.de> ********************************/ if ( !function_exists( 'get_called_class' ) ) { function get_called_class( $bt=false, $l=1 ) { if ( !$bt ) $bt = debug_backtrace(); if ( !isset( $bt[$l] ) ) throw new Exception( 'Cannot find called class -> stack level too deep.' ); if ( !isset( $bt[$l]['type'] ) ) { throw new Exception( 'type not set' ); } else switch ( $bt[$l]['type'] ) { case '::': $function = $bt[$l]['function']; if ( !isset( $bt[$l]['file'] ) ) { $l++; if ( $bt[$l]['function'] == 'call_user_func' || $bt[$l]['function'] == 'call_user_func_array' ) { return $bt[$l]['args'][0][0]; } } $lines = file($bt[$l]['file']); $i = 0; $callerLine = ''; do { $i++; $callerLine = $lines[$bt[$l]['line']-$i] . $callerLine; } while ( stripos( $callerLine, $function ) === false && $i < 500 ); preg_match( '/([a-zA-Z0-9\_]+)::' . $function . '/', $callerLine, $matches ); if ( !isset( $matches[1] ) ) { // must be an edge case. throw new Exception( 'Could not find caller class: originating method call is obscured.' . print_r( $bt, true ) ); } switch ( $matches[1] ) { case 'self': case 'parent': return get_called_class( $bt, $l+1 ); default: return $matches[1]; } // won't get here. case '->': switch ( $bt[$l]['function'] ) { case '__get': // edge case -> get class of calling object if ( !is_object( $bt[$l]['object'] ) ) throw new Exception( 'Edge case fail. __get called on non object.' ); return get_class( $bt[$l]['object'] ); default: return $bt[$l]['class']; } default: throw new Exception( 'Unknown backtrace method type' ); } } } function set_class_var( $class, $varname, $value ) { if ( !class_exists( $class ) ) throw new Exception( 'Class "' . $class . '" does not exist!' ); if ( !property_exists( $class, $varname ) ) throw new Exception( 'Class "' . $class . '" has no property "' . $varname . '"!' ); eval( $class . '::$' . $varname . ' =& $value;' ); return $value; } ?>

« previous php.notes (#165629) next »