0

我有几个数据库表,女巫是使用从一个表继承来构建的,女巫是一种用于创建新表的“模板”,现在我有一组业务逻辑方法,它们处理从模板继承的列,仅使用附加列作为模型展示的参数,它们对逻辑没有意义。

目标是沿所有这些表共享业务逻辑方法,我知道,现在可以通过添加另一个类来扩展 CActiveRecord,并从它扩展每个模型,或者将逻辑打包为行为并将其附加到模型中。但这将需要为每个表/模型至少编写“转储”类文件,但这些表“活”在系统中,并将随着系统生命周期被删除/创建。

有没有办法编写某种“元模型”女巫将作为参数、表名,或者以某种方式为表“即时”创建模型并附加业务逻辑?

我在 Yii 用户板上问过这个问题,但没有找到任何回应:/ 我认为这是某种代码挑战,所以欢迎任何帮助/线索 :)

[编辑]

一些示例:不同客户端设备的表

  • hfc.cable_modem
  • lan.switch_port
  • lan.voip_gateway
  • (在不久的将来,系统中将添加更多“技术”,因此客户端设备的新表,并且有可能放弃对其中一些的支持)

每个表都继承自模板表 client_device 女巫具有以下字段:

  • client_id
  • 服务标识
  • core_device_id
  • (加上一些用于时间戳行为的元列,如创建、更新、更新等)

就像您看到的业务逻辑仅在 ID 上运行,并且每个表都相同,其余列用作设备参数存储/呈现信息。

我的目标是拥有“元模型”客户端设备,女巫将对所有这些表应用业务逻辑,并且仍然为每个表提供对特定字段的访问,而无需为每个表编写模型类(女巫我'每次添加新技术或将来放弃对给定技术的支持时,我都必须这样做)

4

1 回答 1

2

好吧,如果我理解正确,我有一个基于我正在做的类似事情的建议:

我有一个基本的“功能”模型。但是该特征可以是“文本”特征或“图像”特征等。但它们都共享共同的“特征ID”和其他一些列。所以我采取了一种EAV方法。我有一个单一的“功能”表,然后我有每个子类型(文本、图像等)的表。“特征”表中的一列包含子类型信息。然后在基本“特征”模型的“afterFind()”方法中,我查看子类型列。如果子类型是“文本”,我会附上我所做的“文本”类型行为。此行为从子类型表中获取变量并将它们设置为可以像基础模型的属性一样访问。

像这样的东西:

client_device_table:(基表)
-client_id(主键)
-service_id
-core_device_id -device_type
(行为名称,如 CableModemBehavior 或 VoipGatewayBehavior)

cable_modem_table
-core_device_id
-modem_info_1
-modem_into_2

voip_gateway_table
-core_device_id
-gateway_info_1
-gateway_into_2

在 ClientDevice CActiveRecord 模型(基础模型)中:

protected function afterFind() {
  parent::afterFind();
  // remember $this->device_type holds the relevant behavior i.e. CableModemBehavior
  $this->attachBehavior($this->device_type,call_user_func(array($this->device_type, 'model')));
}

行为看起来像这样:

class CableModemBehavior extends CActiveRecordBehavior {
  public modem_info_1;
  public modem_info_2;
  public function attach($owner)
  {
    parent::attach($owner);
    $connection = Yii::app()->getDb();
    $command=$connection->createCommand("SELECT * 
      FROM cable_modem_table 
      WHERE core_device_id=:device_id");
    $command->bindParam(':device_id',$this->owner->core_device_id);
    $data=$command->queryRow();
    $this->modem_info_1 = $data->modem_info_1;
    $this->modem_info_2 = $data->modem_info_2;
  }
}

这是未经测试的,但现在应该发生的是,如果您获得具有 CableModemBehavior 的 ClientDevice 模型,因为它是子类型列条目,您将能够像常规 ClientDevice 属性(client_id)一样访问调制解调器属性(modem_info_1):

ClientDevice->modem_info_1

当然,还有更多的事情要做。这仅适用于“查找”案例。您将需要做更多的工作来让质量属性分配的事情为 $_POSTs 工作,或转移关系,或添加 afterDelete、validate 和 afterSave 方法以支持保存和删除等,但我希望这是一个有用的开始。

您还可以通过在行为中覆盖基本模型的 __get 和 __set 方法来使它变得更好,这样如果请求子类型表中的列,它会透明地从文本表中获取它,执行模式查找以获取列名等。比我在本例中所做的硬编码要好。查看 yiiext 存储库中的EavBehaviorAdvancedArBehavior(或类似的)有助于了解如何使其更流畅。代替每个子类型的行为,您可以有一个通用的行为,只需传入子类型表名。(哦,我真的很喜欢)

干杯!

于 2010-08-26T18:28:58.107 回答