返回

在 ORM 库中从父类获取子类名称的难题:get_called_class 的力量

php

在静态上下文中获取父类中的子类名称:一个 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 库的开发,并允许我们从数据库中获取所需的特定对象实例。

常见问题解答

  1. get_called_class() 函数在哪些 PHP 版本中可用?

    • 5.3 及更高版本
  2. 对于较旧版本的 PHP,如何获取子类名称?

    • 使用 $class = get_class(new static());
  3. 为什么 get_class(parent)get_class(self) 在静态上下文中不能返回子类名称?

    • 因为静态上下文不涉及对象实例。
  4. get_called_class() 函数的优点是什么?

    • 它允许我们在静态上下文中获取调用类的名称。
  5. 在 ORM 库中使用 get_called_class() 函数有什么好处?

    • 它允许我们根据需要从数据库中获取特定对象的实例。