Yii2:为模型分配动态属性并在网格中显示它们
Yii2: Assigning dynamic properties to model and displaying them in a grid
简而言之,应用程序本身非常简单,只有三个表。
产品:
id
name
属性
id
name
slug
产品属性
id
attribute_id
product_id
value
正如您可能猜到的那样,这些属性可能是完全随机的,具有任何内容并且可能有任意数量的属性。每个产品都分配了相同的一组全局属性。有些是空的,有些是满的。
我想要做的是在标准的 Gridview 中显示它们,就好像它是普通模型一样,具有动态预分配的列和值。基本上来说-属性应该作为列。
我尝试扩展主产品模型并在其上使用 ActiveDataProvider class,但无济于事,我为每一行重复获取自定义属性值,就好像缺少某些东西一样。这是我根据 SO 的另一个问题创建的 class。
namespace common\models;
use Yii;
use common\models\Attribute;
use common\models\Product;
class ProductDynamic extends Product {
public function init() {
parent::init();
$attrExists = ProductAttribute::find()->select(['slug','value'])->joinWith(['attributeModel'])->all();
if ($attrExists) {
foreach ($attrExists as $at) {
$this->dynamicFields[$at['slug']] = $at['value'];
}
}
}
private $dynamicFields = [];
public function __get($name) {
if (array_key_exists($name, $this->dynamicFields))
return $this->dynamicFields[$name];
else
return parent::__get($name);
}
public function __set($name, $value) {
if (array_key_exists($name, $this->dynamicFields))
$this->dynamicFields[$name] = $value;
else
parent::__set($name, $value);
}
public function rules() {
return array_merge(parent::rules, $this->dynamicRules);
}
}
我的问题是 - 你会怎么做?如何将属性分配给模型,以便它们充当 ActiveDataProvider 可用的标准数据库加载属性?我想我需要以其他方式检索 ProductAttributes,这样它们就不会重复。见下文。
好的,我想我明白你的想法了...
所以,我认为你可以在 Product 的模型中生成一个属性(我们称之为 ProductAttributeArr),这将是一个数组,然后根据 Product 从数据库中的 Attribute table 中检索属性属性 table 并将它们存储在 ProductAttributeArr.
然后您可以创建一个函数,根据 ProductAttributeArr 的内容动态生成 GridView 的参数。这样它应该可以工作。
由于没有反馈,我自己回答了这个问题,在进一步挖掘之后,我找到了最快但可能不是最好的解决方案。
由于 ProductDynamic class 添加了主要产品模型中的属性,因此我在产品中添加了以下内容以分配正确的列值。当然,肯定还有另一种更简单的方法,如果您知道,请随时发表评论。
public function afterFind() {
$attrs = ProductAttribute::find()->select(['slug', 'value'])->joinWith(['attributeModel'])->where(['product_id' => $this->id])->all();
foreach ($attrs as $a) {
$this->{$a['slug']} = $a['value'];
}
}
简而言之,应用程序本身非常简单,只有三个表。
产品:
id
name
属性
id
name
slug
产品属性
id
attribute_id
product_id
value
正如您可能猜到的那样,这些属性可能是完全随机的,具有任何内容并且可能有任意数量的属性。每个产品都分配了相同的一组全局属性。有些是空的,有些是满的。
我想要做的是在标准的 Gridview 中显示它们,就好像它是普通模型一样,具有动态预分配的列和值。基本上来说-属性应该作为列。
我尝试扩展主产品模型并在其上使用 ActiveDataProvider class,但无济于事,我为每一行重复获取自定义属性值,就好像缺少某些东西一样。这是我根据 SO 的另一个问题创建的 class。
namespace common\models;
use Yii;
use common\models\Attribute;
use common\models\Product;
class ProductDynamic extends Product {
public function init() {
parent::init();
$attrExists = ProductAttribute::find()->select(['slug','value'])->joinWith(['attributeModel'])->all();
if ($attrExists) {
foreach ($attrExists as $at) {
$this->dynamicFields[$at['slug']] = $at['value'];
}
}
}
private $dynamicFields = [];
public function __get($name) {
if (array_key_exists($name, $this->dynamicFields))
return $this->dynamicFields[$name];
else
return parent::__get($name);
}
public function __set($name, $value) {
if (array_key_exists($name, $this->dynamicFields))
$this->dynamicFields[$name] = $value;
else
parent::__set($name, $value);
}
public function rules() {
return array_merge(parent::rules, $this->dynamicRules);
}
}
我的问题是 - 你会怎么做?如何将属性分配给模型,以便它们充当 ActiveDataProvider 可用的标准数据库加载属性?我想我需要以其他方式检索 ProductAttributes,这样它们就不会重复。见下文。
好的,我想我明白你的想法了...
所以,我认为你可以在 Product 的模型中生成一个属性(我们称之为 ProductAttributeArr),这将是一个数组,然后根据 Product 从数据库中的 Attribute table 中检索属性属性 table 并将它们存储在 ProductAttributeArr.
然后您可以创建一个函数,根据 ProductAttributeArr 的内容动态生成 GridView 的参数。这样它应该可以工作。
由于没有反馈,我自己回答了这个问题,在进一步挖掘之后,我找到了最快但可能不是最好的解决方案。
由于 ProductDynamic class 添加了主要产品模型中的属性,因此我在产品中添加了以下内容以分配正确的列值。当然,肯定还有另一种更简单的方法,如果您知道,请随时发表评论。
public function afterFind() {
$attrs = ProductAttribute::find()->select(['slug', 'value'])->joinWith(['attributeModel'])->where(['product_id' => $this->id])->all();
foreach ($attrs as $a) {
$this->{$a['slug']} = $a['value'];
}
}