Classes/Object 函数
在线手册:中文 英文
PHP手册

get_called_class

(PHP 5 >= 5.3.0)

get_called_classthe "Late Static Binding" class name

说明

string get_called_class ( void )

Gets the name of the class the static method is called in.

返回值

Returns the class name. Returns FALSE if called from outside a class.

范例

Example #1 Using 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"

参见


Classes/Object 函数
在线手册:中文 英文
PHP手册
PHP手册 - N: the "Late Static Binding" class name

用户评论:

dsaa at dubli dot com (10-Feb-2012 02:22)

The workarounds to use get_called_class in PHP versions previous to 5.3 didn't quite work for me when the class name in my call was contained in a variable, so I did a couple of modifications to the workarounds proposed.
<?php
/**
* workaround until update to PHP 5.3 takes place
* (Don't make more than one call in the same line, or it will break!!!).
*/
if (!function_exists('get_called_class')):
function
get_called_class()
{
   
$bt = debug_backtrace();
   
$l = count($bt) - 1;
   
$matches = array();
    while(empty(
$matches) && $l > -1){
       
$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);
    }
    return
$matches[1];
}
endif;
?>

maxim at inbox dot ru (27-Dec-2011 03:54)

get_called_class
i was need to get call function from __costruct and found that php 5.3 returns correct, but no one of there functins neither.
So i fix it:
<?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);

if(empty(
$matches[1])){
   
$pp= serialize( $bt[1]["object"]);
   
$nx=strpos($pp,'"')+1;
   
$nx=substr($pp,$nx,strpos($pp,'"'));
    if (!empty(
$nx))
    {
    echo  
" RETURING....: ("$nx  . ")<br>";
    return
$nx;
    }
}
echo  
" RETURING....: (" . $matches[1]  . ")<br>";
    return
$matches[1];
}
endif;
?>

uebele (06-Apr-2011 05:14)

SEE: http://php.net/manual/en/language.oop5.late-static-bindings.php

I think it is worth mentioning on this page, that many uses of the value returned by get_called_function() could be handled with the new use of the old keyword static, as in
<?php
static::$foo;
?>

versus
<?php
$that
=get_called_class();
$that::$foo;
?>

I had been using $that:: as my conventional replacement for self:: until my googling landed me the url above.  I have replaced all uses of $that with static with success both as
<?php
static::$foo; //and...
new static();
?>

Since static:: is listed with the limitation: "Another difference is that static:: can only refer to static properties." one may still need to use a $that:: to call static functions; though I have not yet needed this semantic.

webmaster at easy-coding dot de (12-Mar-2010 04:03)

if you cannot avoid that carriage return characters will be used as windows linebreaks, you should set

<?php ini_set("auto_detect_line_endings", 1); ?>

otherwise the solutions posted here will fail.

Abhi Beckert (29-Oct-2009 04: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'

mucahitkahveci at yahoo dot com (03-Sep-2009 03: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 (11-Aug-2009 05: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 02: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 12: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 07: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 10: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 08: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 (21-Feb-2009 06: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 (08-Oct-2008 08: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