好吧,如果我理解正确,我有一个基于我正在做的类似事情的建议:
我有一个基本的“功能”模型。但是该特征可以是“文本”特征或“图像”特征等。但它们都共享共同的“特征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 存储库中的EavBehavior和AdvancedArBehavior(或类似的)有助于了解如何使其更流畅。代替每个子类型的行为,您可以有一个通用的行为,只需传入子类型表名。(哦,我真的很喜欢)
干杯!