從 PHP 5.5 開始,您也可以使用「static::class」來取得被呼叫的類別名稱。
<?php
class Bar {
public static function test() {
var_dump(static::class);
}
}
class Foo extends Bar {
}
Foo::test();
Bar::test();
?>
輸出
字串(3) "Foo"
字串(3) "Bar"
(PHP 5 >= 5.3.0, PHP 7, PHP 8)
get_called_class — 「後期靜態綁定」的類別名稱
此函式沒有參數。
傳回類別名稱。
範例 #1 使用 get_called_class()
<?php
class foo {
public static function test() {
var_dump(get_called_class());
}
}
class bar extends foo {
}
foo::test();
bar::test();
?>
以上範例會輸出:
string(3) "foo" string(3) "bar"
從 PHP 5.5 開始,您也可以使用「static::class」來取得被呼叫的類別名稱。
<?php
class Bar {
public static function test() {
var_dump(static::class);
}
}
class Foo extends Bar {
}
Foo::test();
Bar::test();
?>
輸出
字串(3) "Foo"
字串(3) "Bar"
在閉包範圍內的 get_called_class()
<?PHP
抽象類別 Base
{
protected static $stub = ['baz'];
//final public function boot()
static public function boot()
{
echo __METHOD__.'-> '.get_called_class().PHP_EOL;
array_walk(static::$stub, function()
{
echo __METHOD__.'-> '.get_called_class().PHP_EOL;
});
}
public function __construct()
{
self::boot();
echo __METHOD__.'-> '.get_called_class().PHP_EOL;
array_walk(static::$stub, function()
{
echo __METHOD__.'-> '.get_called_class().PHP_EOL;
});
}
}
類別 Sub 延伸 Base
{
}
// 靜態呼叫 boot
Base::boot(); echo PHP_EOL;
// Base::boot -> Base
// Base::{closure} -> Base
Sub::boot(); echo PHP_EOL;
// Base::boot -> Sub
// Base::{closure} -> Base
new Sub;
// Base::boot -> Sub
// Base::{closure} -> Base
// Base->__construct -> Sub
// Base->{closure} -> Sub
// 實例化後呼叫 boot
new Sub;
// Base::boot -> Sub
// Base::{closure} -> Base
// Base->__construct -> Sub
// Base->{closure} -> Sub
?>
命名空間 root;
類別 Factor {
protected static $instance = null;
private function __construct() {
}
public static function getInstance() {
if (!self::$instance) {
$name = get_called_class();
self::$instance = new $name();
}
return self::$instance;
}
}
命名空間 admin\test;
use root\Factor;
類別 Single 延伸 Factor {
public function abc() {
return 'abc';
}
}
命名空間 index;
use admin\test\Single;
類別 Index {
public function get() {
return Single::getInstance();
}
}
$index = new Index();
var_dump($index->get());
結果是
object(admin\test\Single)#2 (0) {
}
參考: https://php.dev.org.tw/manual/en/language.oop5.late-static-bindings.php
我認為值得在此頁面上提及的是,許多 get_called_function() 返回值的用法可以用舊關鍵字 static 的新用法來處理,例如
<?php
static::$foo;
?>
對比
<?php
$that=get_called_class();
$that::$foo;
?>
我之前一直使用 $that:: 作為 self:: 的慣用替代方案,直到我在 Google 上搜尋到上述網址。我已成功將所有 $that 的用法都替換為 static,例如:
<?php
static::$foo; //以及...
new static();
?>
由於 static:: 有其限制:「另一個不同之處是 static:: 只能參考靜態屬性。」因此,可能仍然需要使用 $that:: 來呼叫靜態函式;雖然我目前還沒有用到這種語法。
在 PHP 5.6(7 以下版本)中以靜態方式呼叫動態方法時,雖然允許這樣做,但卻無法正常運作,它會錯誤地評估呼叫我們目標類別的類別,因此包含的方法必須是靜態的。
在 PHP 5.3 中,可以使用 get_called_class 撰寫一個完全自包含的 Singleton 基礎類別。
<?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 連線到資料庫
}
public function __destruct() {
// @todo 關閉資料庫連線
}
}
$oDbConn = new DatabaseConnection(); // 致命錯誤
$oDbConn = DatabaseConnection::getInstance(); // 回傳單一實例
?>
如果您呼叫一個靜態的 getInstance() 函式,從另一個類別建立一個類別的實例,則該函式必須是靜態的,如果不是靜態的,則會回傳呼叫者類別的原始名稱,而不是目前類別的名稱。
範例
<?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(); // 將會回傳 "a"
echo $b->getXName(); // 將會回傳 "b"
echo $a->getXStaticName(); // 將會回傳 "x"
echo $b->getXStaticName(); // 將會回傳 "x"
?>
注意,如果你的方法沒有宣告為靜態 (static),這段程式碼的行為將不如預期!例如:
<?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 "基本範例\n";
foo::test();
bar::test();
echo "沒有 static 宣告的基本範例\n";
foo::testTwo();
bar::testTwo();
echo "在類別中\n";
$abc = new abc();
$abc->test();
echo "在沒有 static 宣告的類別中\n";
$abc->testTwo();
?>
結果是
基本範例
字串 'foo'
字串 'bar'
沒有 static 宣告的基本範例
字串 'foo'
字串 'bar'
在類別中
字串 'foo'
字串 'bar'
在沒有 static 宣告的類別中
字串 'abc'
字串 'abc'
這是一個取得類別繼承樹的簡單方法,無論函式實際定義在哪個類別中。也可以作為靜態函式方法使用。
<?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