【问题标题】:Yii framework "meta db model" creation + postgres inheritanceYii框架“元数据库模型”创建+postgres继承
【发布时间】:2011-04-03 15:16:01
【问题描述】:

我的数据库表很少,女巫是使用从一个表继承来构建的仅用作模型表示的参数,它们对逻辑没有意义。

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

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

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

[编辑]

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

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

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

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

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

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

【问题讨论】:

  • 可能有一种巧妙的方法可以做到这一点,使用行为将模型动作动态附加到单个通用模型类(并覆盖它的表名),但没有一些更具体的例子来说明你想要做什么做(即代码)我不能确定。愿意更详细地解释一下吗?谢谢

标签: php code-generation yii database-design


【解决方案1】:

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

我有一个基本的“功能”模型。但是该特征可以是“文本”特征或“图像”特征等。但它们都共享共同的“特征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;
  }
}

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

ClientDevice->modem_info_1

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

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

干杯!

【讨论】:

  • 非常感谢 m8 :) 我不确定你的方式是否适合我的环境,但肯定会深入研究,显示新的做事方式 :) 我会不断更新有关此的信息项目,如果您能找到更多“提示”,我会很高兴:)
猜你喜欢
  • 2016-03-26
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2011-03-03
  • 2017-09-04
  • 1970-01-01
相关资源
最近更新 更多