note 93799 modified in function.get-called-class by danbrown
| From: | danbrown@php.net | Date: | Wed, 30 Sep 2009 15:42:53 +0000 |
| Subject: | note 93799 modified in function.get-called-class by danbrown | ||
| References: | 1 | Groups: | php.notes |
| Request: | Send a blank email to php-notes+get-161177@lists.php.net to get a copy of this message | ||
I've made some additions to mucahitkahveci's method, but ended up re-writing it to suit
certain needs and conventions.
It passes the example test cases on the late static bindings page with the <?php
static::funtion_name() ?> calls converted to
<?php
$static_class = get_called_class();
call_user_func(array($static_class,'function_name'));
?>
I tested it in PHP 5.2.4 and came across no discrepancies from the 5.3 behavior, however the more
eyes the better.
Also, I've included the edge case where a static property can be called on a class e.g.
<?php
class A {
public function __get($var) {
return get_class_name();
}
}
$instance = new A();
echo $instance->foo;
?>
However this probably doesn't cover all edge cases, so the function still needs work.
And here it is...
<?php
/********************************
* Retro-support of get_called_class()
* Tested and works in PHP 5.2.4
* http://www.sol1.com.au/
********************************/
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 '::':
$lines = file($bt[$l]['file']);
$i = 0;
$callerLine = '';
do {
$i++;
$callerLine = $lines[$bt[$l]['line']-$i] . $callerLine;
} while (strpos($callerLine,$bt[$l]['function']) === false);
preg_match('/([a-zA-Z0-9\_]+)::'.$bt[$l]['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.");
}
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");
}
}
}
?>
--was--
I've made some additions to mucahitkahveci's method, but ended up re-writing it to suit
certain needs and conventions.
It passes the example test cases on the late static bindings page with the <?
static::funtion_name() ?> calls converted to
<?
$static_class = get_called_class();
call_user_func(array($static_class,'function_name'));
?>
I tested it in PHP 5.2.4 and came across no discrepancies from the 5.3 behavior, however the more
eyes the better.
Also, I've included the edge case where a static property can be called on a class e.g.
<?php
class A {
public function __get($var) {
return get_class_name();
}
}
$instance = new A();
echo $instance->foo;
?>
However this probably doesn't cover all edge cases, so the function still needs work.
And here it is...
<?php
/********************************
* Retro-support of get_called_class()
* Tested and works in PHP 5.2.4
* http://www.sol1.com.au/
********************************/
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 '::':
$lines = file($bt[$l]['file']);
$i = 0;
$callerLine = '';
do {
$i++;
$callerLine = $lines[$bt[$l]['line']-$i] . $callerLine;
} while (strpos($callerLine,$bt[$l]['function']) === false);
preg_match('/([a-zA-Z0-9\_]+)::'.$bt[$l]['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.");
}
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");
}
}
}
http://php.net/manual/en/function.get-called-class.php