Yii框架“元数据库模型”创建+ postgres继承

时间:2010-08-25 09:44:43

标签: php code-generation yii database-design

我有几个数据库表,使用一个表的继承来构建女巫是一种用于创建新表的“模板”,现在我有一套业务逻辑方法,可以在列上继承模板,附加列仅用作描述模型的参数,它们对逻辑没有意义。

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

有没有办法写一些“元模型”女巫作为一个参数,表名,或者某种方式为“动态”创建表格模型并附加到它的商业逻辑?

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

[编辑]

一些样本: 用于不同客户端设备的表

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

每个表都继承自模板表client_device,其中包含以下字段:

  • 的client_id
  • 的service_id
  • core_device_id
  • (加上一些用于时间戳行为的元列,如创建,更新,更新程序等)。

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

我的目标是拥有“元模型”客户端设备,将所有这些表应用业务逻辑,并且仍然为每个表提供访问特定字段,而不必为每个表编写模型类(我将不得不每次都要做新技术,或者将来会放弃对特定技术的支持。

1 个答案:

答案 0 :(得分:2)

好吧,如果我理解你的话,我会根据我正在做的事情提出一个建议:

我有一个基本的“功能”模型。但该功能可以是“文本”功能,或“图像”功能等。但它们都共享共同的“功能ID”和其他几列。所以我采用了EAV方法。我有一个“功能”表,然后我有一个表为每个子类型(文本,图像等)。 “feature”表中的一列包含子类型信息。然后在基于“特征”模型的“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模型作为它的子类型列条目,你将能够像访问调制解调器属性(modem_info_1)一样常规的ClientDevice属性(client_id):

ClientDevice-&GT; modem_info_1

当然,还有比这更多的事情。这仅适用于“查找”案例。你需要做一些更多的工作来让mass属性赋值对于$ _POSTs起作用,或者传递Relations,或者添加afterDelete,validate和afterSave方法以支持保存和删除等,但我希望这是一个有用的启动。

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

干杯!