2

这个问题与我想要达到的目标非常相似,但是正如几乎每个问题的答案都在极其详细的说明中所表明的那样,这是一个糟糕的设计。

PHP,区分内部和外部类方法调用

这是我想要实现的目标:
跟踪在低活动配置表上执行的所有操作,以便可以将更改传播到生产和 QA 数据库。(配置表 = 配置存储在表中。)

这是我的问题的概要:
Yii 中的所有模型都扩展自 CActiveRecord 类,该类提供了一些操作模型实例的方法。

让我们将它们分为两类:

  1. 非基元- 触发事件,如 onBeforeDelete、onAfterFind、onAfterSave 等(例如:https ://github.com/yiisoft/yii/blob/1.1.13/framework/db/ar/CActiveRecord.php#L1061 )
  2. Primitives - 直接创建和执行命令而不触发事件 - 即充当查询生成器。(例如:https ://github.com/yiisoft/yii/blob/1.1.13/framework/db/ar/CActiveRecord.php#L1684 )

现在,这些原语也是公共成员,因此可以根据用户的判断从类外部调用 -他们将修改表而不触发任何事件。

这些是我想出的解决方案:

  1. 为所有开发人员制定仅使用非原始方法的指南。
  2. 将 CActiveRecord 封装在我自己的模型类中,并且只公开非基元。

案例 1将更容易实现,但更容易出错,因为有时一些开发人员可能会忘记限制并使用原始方法。

案例 2将要求我编写大量代码/方法来公开我希望使用的方法。此外,如果 Yii CActiveRecord 和我的 ActiveRecord 类没有相同的接口,这可能会引起混淆。

在我看来,一个更好的解决方案是允许在内部使用原语同时限制外部调用,即使用私有/公共访问说明符。(这已经与我在案例 2 中提供的原因相矛盾,但这是我能想出的唯一解决方案。)由于我不能在没有封装的情况下使用私有/公共说明符,而且我不能封装,所以我想区分函数是外部调用还是内部调用的方法。debug_backtrace是一个可行的解决方案,但我在这里是为了一个更优雅、更少hacky 的解决方案,或者一个明确的声明,即这是不可能的。

4

1 回答 1

2

首先,你应该退后一步,想想为什么会有如此不同的行为。您调用的非原始方法应该在模型实例上调用:

$ar = new Something();
$ar->update(...);

虽然您调用原语的方法应该在模型本身上调用:

Something::model()->updateByPk(...);

按理说,在第二种情况下引发事件是没有意义的,因为

  1. 您根本不应该直接与之合作::model(),并且
  2. 根据方法的不同,该操作可能会影响 PHP 中没有对应模型实例的多条记录

因此,寻求解决方案应该从回答以下两个问题开始:

  1. 在一个完美的世界中,当调用模型上的任何方法时,您将如何得到通知?(显然,该方法需要是原始的才能使调用有意义)。
  2. 在一个完美的世界中,如何通知您影响未知(在 PHP 中)数量的记录的操作?
于 2013-06-13T08:44:08.863 回答