我有几个数据库表,使用一个表的继承来构建女巫是一种用于创建新表的“模板”,现在我有一套业务逻辑方法,可以在列上继承模板,附加列仅用作描述模型的参数,它们对逻辑没有意义。
目标是在所有表中共享业务逻辑方法,我知道,现在可以通过添加另一个类扩展CActiveRecord,并从每个模型扩展它,或将逻辑打包为行为并将其附加到楷模。 但这需要为每个表/模型至少写入“dump”类文件,但这些表在系统中“活动”,并将在系统生命周期中删除/创建。
有没有办法写一些“元模型”女巫作为一个参数,表名,或者某种方式为“动态”创建表格模型并附加到它的商业逻辑?
我在Yii用户板上问了这个问题,但没有找到任何回复:/ 我认为这是一种代码挑战,所以欢迎任何帮助/线索:)
[编辑]
一些样本: 用于不同客户端设备的表
每个表都继承自模板表client_device,其中包含以下字段:
就像您看到业务逻辑仅在ID上运行,并且每个表都相同,其余列用作设备参数存储/表示信息。
我的目标是拥有“元模型”客户端设备,将所有这些表应用业务逻辑,并且仍然为每个表提供访问特定字段,而不必为每个表编写模型类(我将不得不每次都要做新技术,或者将来会放弃对特定技术的支持。
答案 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将有助于了解如何使其更流畅。您可以使用通用行为而不是每个子类型的行为,只需传入子类型表名。 (噢,我真的很喜欢)
干杯!