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'];
    }
}