在 ORM 库中从父类获取子类名称的难题:get_called_class 的力量
2024-03-09 10:25:14
在静态上下文中获取父类中的子类名称:一个 ORM 库的难题
引言
在构建一个注重重用性和简洁性的 ORM 库时,我遇到了一个看似微不足道的继承限制,差点让我抓狂。本文将探讨这个问题,并详细阐述一种解决方案,它将帮助你有效地从父类中获取子类名称,即使是在静态上下文中。
问题陈述
ORM(对象关系映射器)的作用是简化对象与数据库之间的交互。理想情况下,我们希望用简单的一行代码从数据库中获取一个对象的实例,而不管对象属于哪个类。
让我们考虑以下代码:
class BaseModel {
static public function get(/* varargs */) {
$class = get_class(parent); // value: bool(false)
$class = get_class(self); // value: bool(false)
$class = get_class(); // value: string(9) "BaseModel"
$class = __CLASS__; // value: string(9) "BaseModel"
// [...]
}
}
class User extends BaseModel {
protected $table = 'users';
protected $fields = array('id', 'name');
protected $primary_keys = array('id');
}
$my_user = User::get(3);
在这种情况下,我们希望从数据库中获取一个 User
实例。然而,使用 get_class(parent)
、get_class(self)
、get_class()
和 __CLASS__
返回的都是父类 BaseModel
的名称。
解决方案:get_called_class()
为了解决这个问题,我们可以使用 get_called_class()
函数。该函数返回调用类的名称,即使它是在静态上下文中调用的。
修改后的代码
class BaseModel {
static public function get(/* varargs */) {
$class = get_called_class(); // value: string(3) "User"
// [...]
}
}
现在,get_called_class()
函数将正确返回子类的名称,User
。
注意
需要注意的是,get_called_class()
函数仅在 PHP 5.3 及更高版本中可用。对于较旧版本的 PHP,可以使用以下代码:
$class = get_class(new static());
结论
通过使用 get_called_class()
函数,我们能够在父类中获取子类名称,从而简化了 ORM 库的开发,并允许我们从数据库中获取所需的特定对象实例。
常见问题解答
-
get_called_class() 函数在哪些 PHP 版本中可用?
- 5.3 及更高版本
-
对于较旧版本的 PHP,如何获取子类名称?
- 使用
$class = get_class(new static());
- 使用
-
为什么
get_class(parent)
和get_class(self)
在静态上下文中不能返回子类名称?- 因为静态上下文不涉及对象实例。
-
get_called_class()
函数的优点是什么?- 它允许我们在静态上下文中获取调用类的名称。
-
在 ORM 库中使用
get_called_class()
函数有什么好处?- 它允许我们根据需要从数据库中获取特定对象的实例。