downloads | documentation | faq | getting help | mailing lists | licenses | wiki | reporting bugs | php.net sites | links | conferences | my php.net

search for in the

get_class_methods> <class_exists
Last updated: Fri, 13 Nov 2009

view this page in

get_called_class

(PHP 5 >= 5.3.0)

get_called_class"静的遅延束縛" のクラス名

説明

string get_called_class ( void )

静的メソッドのコール元のクラス名を取得します。

返り値

クラス名を返します。クラスの外部からコールされた場合は FALSE を返します。

例1 get_called_class() の使用法

<?php

class foo {
    static public function 
test() {
        
var_dump(get_called_class());
    }
}

class 
bar extends foo {
}

foo::test();
bar::test();

?>

上の例の出力は以下となります。

string(3) "foo"
string(3) "bar"

参考

  • get_parent_class() - オブジェクトの親クラスの名前を取得する
  • get_class() - オブジェクトのクラス名を返す
  • is_subclass_of() - あるオブジェクトが指定したクラスのサブクラスに属するかどうかを調べる



get_class_methods> <class_exists
Last updated: Fri, 13 Nov 2009
 
add a note add a note User Contributed Notes
get_called_class
Abhi Beckert
29-Oct-2009 01:41
Beware that this does not behave as expected if your method is not declared as static! For example:

<?php

class foo {
  static public function
test() {
   
var_dump(get_called_class());
  }
 
  public function
testTwo() {
   
var_dump(get_called_class());
  }
}

class
bar extends foo {
}

class
abc {
  function
test() {
   
foo::test();
   
bar::test();
  }
 
  function
testTwo() {
   
foo::testTwo();
   
bar::testTwo();
  }
}

echo
"basic\n";
foo::test();
bar::test();

echo
"basic without static declaration\n";
foo::testTwo();
bar::testTwo();

echo
"in a class\n";
$abc = new abc();
$abc->test();

echo
"in a class without static declaration\n";
$abc->testTwo();

?>

The result is:

basic
string 'foo'
string 'bar'

basic without static declaration
string 'foo'
string 'bar'

in a class
string 'foo'
string 'bar'

in a class without static declaration
string 'abc'
string 'abc'
laurence+nospam at sol1 dot com dot au
30-Sep-2009 04:32
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 (
stripos($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");
    }
}
}
?>

[EDIT BY danbrown AT php DOT net: Contains a fix provided by (webmaster AT easy DASH coding DOT de) on 10-NOV-09 with the following explanation: since method calls are caseinsensitive you should use stripos instead of strpos.  Otherwise you will end up with a "Undefined offset: -1" notice and the error "Could not find caller class."]
mucahitkahveci at yahoo dot com
03-Sep-2009 11:21
Addition to tom at r dot je:
It is fine but does not work for method calls like:

<?php
class Car
{
    static function
getClass()
    {
        echo
get_called_class();
    }
}
$method='getClass';
Car::$method(); //prints nothing
?>

So I developed to meet also this issue, and add one extra line not to cause notice errors:

<?php
if(!function_exists('get_called_class')) {
function
get_called_class() {
   
$matches=array();
   
$bt = debug_backtrace();
   
$l = 0;
    do {
       
$l++;
        if(isset(
$bt[$l]['class']) AND !empty($bt[$l]['class'])) {
            return
$bt[$l]['class'];
        }
       
$lines = file($bt[$l]['file']);
       
$callerLine = $lines[$bt[$l]['line']-1];
       
preg_match('/([a-zA-Z0-9\_]+)::'.$bt[$l]['function'].'/',
                  
$callerLine,
                  
$matches);
        if (!isset(
$matches[1])) $matches[1]=NULL; //for notices
       
if ($matches[1] == 'self') {
              
$line = $bt[$l]['line']-1;
               while (
$line > 0 && strpos($lines[$line], 'class') === false) {
                  
$line--;                 
               }
              
preg_match('/class[\s]+(.+?)[\s]+/si', $lines[$line], $matches);
       }
    }
    while (
$matches[1] == 'parent'  && $matches[1]);
    return
$matches[1];
}
}
?>
tom at r dot je
12-Aug-2009 01:18
I've further extended spidgorny at gmail dot com's 5.2 get_called_class() solution to also account for self:: calls. It works backwards up the file to find the class definition.

<?php
if(!function_exists('get_called_class')) {
function
get_called_class() {
   
$bt = debug_backtrace();
   
$l = 0;
    do {
       
$l++;
       
$lines = file($bt[$l]['file']);
       
$callerLine = $lines[$bt[$l]['line']-1];
       
preg_match('/([a-zA-Z0-9\_]+)::'.$bt[$l]['function'].'/',
                  
$callerLine,
                  
$matches);
                  
       if (
$matches[1] == 'self') {
              
$line = $bt[$l]['line']-1;
               while (
$line > 0 && strpos($lines[$line], 'class') === false) {
                  
$line--;                  
               }
              
preg_match('/class[\s]+(.+?)[\s]+/si', $lines[$line], $matches);
       }
    }
    while (
$matches[1] == 'parent'  && $matches[1]);
    return
$matches[1];
  }
}

?>

Not pretty but works until servers can be upgraded.
php at itronic dot at
07-Aug-2009 10:53
If you call a static getInstance() function to create a instance of a class from another class, this function have to be static, if it is not static the original name of the caller class and not of the current class get returned.

example:

<?php

class a {
  function
getXName() {
     return
x::getClassName();
  }
  function
getXStaticName() {
     return
x::getStaticClassName();
  }

}

class
b extends a {
}

class
x {
  public function
getClassName() {
    return
get_called_class();
  }
  public static function
getStaticClassName() {
    return
get_called_class();
  }
}

$a = new a();

$b = new b();

echo
$a->getXName(); // will return "a"
echo $b->getXName(); // will return "b"

echo $a->getXStaticName(); // will return "x"
echo $b->getXStaticName(); // will return "x"

?>
steve at visual77 dot com
30-Jul-2009 08:21
I've furthered enhanced the attempts to fix get_called_class() for PHP 5.2 Using a class and some static properties, we can keep track of how many times it has already processed the current line, so multiple calls on the same line will still function properly.

<?php

if(!function_exists('get_called_class')) {
    class
class_tools {
        static
$i = 0;
        static
$fl = null;
       
        static function
get_called() {
           
$bt = debug_backtrace();
           
            if(
self::$fl == $bt[2]['file'].$bt[2]['line']) {
               
self::$i++;
            } else {
               
self::$i = 0;
               
self::$fl = $bt[2]['file'].$bt[2]['line'];
            }
           
           
$lines = file($bt[2]['file']);
           
           
preg_match_all('/([a-zA-Z0-9\_]+)::'.$bt[2]['function'].'/',
               
$lines[$bt[2]['line']-1],
               
$matches);
           
            return
$matches[1][self::$i];
        }
    }

    function
get_called_class() {
        return
class_tools::get_called_class();
    }
}

?>
aashley at php dot net
27-Jul-2009 03:06
Small change to spidgorny at gmail dot com's example so that it works with static calls as well.

Change:
} while ($matches[1] == 'parent' && $matches[1]);

to:
} while( in_array($matches[1], array('parent', 'self')) && $matches[1]);
spidgorny at gmail dot com
14-Jul-2009 06:32
My modification to the get_called_class() simulation function, which takes care of the parent:: calls. It goes further into the backtrace to find the first non "parent" call. This way we pop-up to the original caller class. I'm not sure if this is the default behavior of the original PHP 5.3 function.
<?php
// http://us.php.net/manual/en/function.get-called-class.php#89478
if (!function_exists('get_called_class')):

  function
get_called_class() {
   
$bt = debug_backtrace();
   
//debug($bt);
   
$l = 0;
    do {
       
$l++;
       
$lines = file($bt[$l]['file']);
       
$callerLine = $lines[$bt[$l]['line']-1];
       
//debug($callerLine);
       
preg_match('/([a-zA-Z0-9\_]+)::'.$bt[$l]['function'].'/',
                  
$callerLine,
                  
$matches);
    } while (
$matches[1] == 'parent' && $matches[1]);
    return
$matches[1];
  }

endif;
?>
progman at centrum dot sk
10-Mar-2009 05:49
Simplified version:

<?php if (!function_exists('get_called_class')):

  function
get_called_class()
  {
   
$bt = debug_backtrace();
   
$lines = file($bt[1]['file']);
   
preg_match('/([a-zA-Z0-9\_]+)::'.$bt[1]['function'].'/',
              
$lines[$bt[1]['line']-1],
              
$matches);
    return
$matches[1];
  }

endif;
?>

When you use this function in singleton, mind there can by only one getInstance() call per line:

<?php

 
abstract class Singleton  {  ... }
  class
MySingleton1 extends Singleton { ... }
  class
MySingleton2 extends Singleton  { ... }

 
// this will work:
 
$s1 = MySingleton1::getInstance();
 
$s2 = MySingleton2::getInstance();

 
// here will be problem:
 
$s1 = MySingleton1::getInstance(); $s2 = MySingleton2::getInstance();

?>
a dot cudbard-bell at sussex dot ac dot uk
22-Feb-2009 03:03
Here's a simple way of getting the inheritance tree of a class, no matter which class the function was actually defined in. Will work as a static function method too.

<?php
class A {
    public function
get_class_tree(){
       
$cur_class = get_called_class();
        do {
            echo
$cur_class;           
        }
        while(
$cur_class = get_parent_class($cur_class));
    }
}

class
B {

}

class
C {

}

$foo = new C();
$foo->get_class_tree();

?>

CBA
danbettles at yahoo dot co dot uk
09-Oct-2008 04:00
It is possible to write a completely self-contained Singleton base class in PHP 5.3 using get_called_class.

<?php

abstract class Singleton {

    protected function
__construct() {
    }

    final public static function
getInstance() {
        static
$aoInstance = array();

       
$calledClassName = get_called_class();

        if (! isset (
$aoInstance[$calledClassName])) {
           
$aoInstance[$calledClassName] = new $calledClassName();
        }

        return
$aoInstance[$calledClassName];
    }

    final private function
__clone() {
    }
}

class
DatabaseConnection extends Singleton {

    protected
$connection;

    protected function
__construct() {
       
// @todo Connect to the database
   
}

    public function
__destruct() {
       
// @todo Drop the connection to the database
   
}
}

$oDbConn = new DatabaseConnection();  // Fatal error

$oDbConn = DatabaseConnection::getInstance();  // Returns single instance
?>

Full write-up in Oct 2008: http://danbettles.blogspot.com

get_class_methods> <class_exists
Last updated: Fri, 13 Nov 2009
 
 
show source | credits | stats | sitemap | contact | advertising | mirror sites