根据对方法的外部或内部调用选择性地公开函数

时间:2013-06-13 08:14:47

标签: php oop inheritance yii encapsulation

这个问题与我正在努力实现的问题非常相似,但正如在问题的几乎每个答案中都表达得非常详细,这是一个糟糕的设计。

  

PHP, distinguish between internal and external class method call

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

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

让我们将这些分为两类:

  1. 非基元 - 触发事件,如onBeforeDelete,onAfterFind,onAfterSave等(例如:https://github.com/yiisoft/yii/blob/1.1.13/framework/db/ar/CActiveRecord.php#L1061
  2. 基元 - 直接创建和执行命令而不触发事件 - 即充当查询生成器。 (例如:https://github.com/yiisoft/yii/blob/1.1.13/framework/db/ar/CActiveRecord.php#L1684
  3. 现在,这些原语也是公共成员,因此可以由用户自行决定从类外调用 - 并且他们将修改表而不会触发任何事件。

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

    1. 为所有开发人员制定指南,仅使用非原始方法。
    2. 将CActiveRecord封装在我自己的模型类中,并仅公开非基元。
    3. 案例1 将更容易实现,但更容易出错,因为有些开发人员可能会忘记限制并使用原始方法。

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

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

1 个答案:

答案 0 :(得分:2)

首先,您应退后一步,想一想为什么行为存在这样的差异。您调用非原语的方法应该在模型实例上调用:

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

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

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

理所当然地说,在第二种情况下提出事件是没有意义的,因为

  1. 您根本不应该直接使用::model()
  2. 取决于方法,操作可能会影响PHP中没有相应模型实例的多个记录
  3. 因此,寻求解决方案应该从你回答这两个问题开始:

    1. 在完美的世界中,如何在模型上调用任何方法时收到通知? (显然,对于有意义的调用,该方法需要是原始的。)
    2. 在一个完美的世界中,您将如何收到影响未知(PHP)记录数量的操作的通知?