【发布时间】:2025-12-04 03:30:02
【问题描述】:
我同时使用魔术方法_call 和_callStatic 来实现我自己的ORM/Activerow 之类的东西。它们主要用于捕获某些函数调用:__call 负责 getter 和 setter,__callStatic 负责 findBy 方法(例如 findById)。
为了映射外键,我正在尝试将调用转换为例如getArticle 返回 Article::findById() 的值。为此,我在__call 中使用了这个案例:
if (strstr($property, "_id")) {
return $foreignClass::findById($this->getId());
}
其中$property 是__call 中set 或get 之后的子字符串,$foreignClass 是字符串的其余部分。因此,在调用 getArticle 的情况下,$property 将是 get,$foreignClass 将是 Article。
我放置了一些回声以确保值正确。然而,我的__call 方法被调用而不是我的__callStatic。如果我创建一个隐式静态方法findById,它会被调用(因此它确实将其识别为静态调用)。如果我专门打电话给Article::findById(),__call 也会接听。
这是相对较新的__callStatic 的错误,还是我做错了什么?
编辑: 问题似乎出在这部分:
_call() 在对象上下文中调用不可访问的方法时被触发。
在静态上下文中调用不可访问的方法时会触发 __callStatic()。
虽然我是在一个类上调用它,但我是从一个对象上下文中调用它。在这种情况下有没有办法进入静态上下文?
【问题讨论】:
-
我有一种可怕的感觉,这里缺少重要的信息。魔术方法定义在哪些类中?他们被称为哪个类?前面提到的类是同一继承树的成员吗?如果有,他们的关系是什么?
-
这里的继承树是DBObject(我在这里展示了代码)->Article->Activity。文章和活动没有覆盖相关代码,所有这些逻辑都发生在 DBObject 中。我现在已将代码更改为使用 __get 和 __set 而不是 __call,而且现在似乎可以正确触发 __callStatic。
-
所以
$foreignClass是Article并且在Activity的上下文中调用该方法。这使得Article成为祖先类。问题来了。 -
$foreignClass 在这种情况下确实是 Article 。变量指的是外键所指的表/对象。在这种情况下,Activity 指向的是 Article,但它也可能是指向 Article 的 Comment(Comment 也是 DBObject 的子类)。计划是在这里实现类所称的唯一真正的区别;它使用该名称插入到正确的表中。既然 Article 和 Activity 都没有覆盖魔法方法,那么它们的行为不应该和 DBObject 一样吗?
标签: php activerecord orm getter-setter