【问题标题】:Yii2 get column from junction table and use in gridviewYii2从连接表中获取列并在gridview中使用
【发布时间】:2015-05-26 13:35:06
【问题描述】:

我的部分架构如图所示:

联结表映射哪些项目属于哪个类别,“特色”列将项目标记为该类别中的特色。

我需要做的是获取特定类别中所有项目的列表,包括联结表中的“特色”属性,并将该数据传递到网格视图中进行显示。

我为category_item 表创建了一个模型,并尝试实施here 提出的解决方案,但我如何访问数据并将其传递到gridview 中?

类别模型

public function getCategoryItems()
{
    return $this->hasMany(CategoryItem::className(), ['category_id' => 'id']);
}

public function getItems()
{
    return $this->hasMany(Item::className(), ['id' => 'item_id'])->viaTable('{{%category_item}}', ['category_id' => 'id']);
}

类别搜索模型

public function search($params)
{
    $query = Category::find()->with('items')->with('categoryItems');

    $dataProvider = new ActiveDataProvider([
        'query' => $query,
    ]);

    $this->load($params);

    if (!$this->validate()) {
        return $dataProvider;
    }

    $query->andFilterWhere([
        'id' => $this->id,
        'type' => $this->type,
    ]);

    $query->andFilterWhere(['like', 'title', $this->title])
        ->andFilterWhere(['like', 'description', $this->description]);

    return $dataProvider;
}

物品模型

public function getItemCategories()
{
    return $this->hasMany(CategoryItem::className(), ['item_id' => 'id']);
}

public function getCategories()
{
    return $this->hasMany(Category::className(), ['id' => 'category_id'])->viaTable('{{%category_item}}', ['item_id' => 'id']);
}

控制器

public function actionCategory($id = null)
{
    if($id == null) {
        $dataProvider = new ActiveDataProvider([
            'query' => Category::find()->all(),
        ]);

        return $this->render('category', [
                'dataProvider' => $dataProvider,
        ]);
    } else {

        $category = Category::findOne($id);

        if($category) {
            $searchModel = new CategorySearch();

            $itemsDataProvider = new ActiveDataProvider([
                'query' =>  $searchModel->search(['CategorySearch'=>['id'=>$id]]),
            ]);

            return $this->render('editCategory', [
                'itemsDataProvider' => $itemsDataProvider
                'model' => $category,
            ]);
        } else {
            throw new NotFoundHttpException('The requested page does not exist.');
        }
    }
}

查看

<div class="row">
    <div class="col-md-12">
        <h2>Items</h2>
        <?= GridView::widget([
            'dataProvider' => $itemsDataProvider,
            'columns' => [

                'id',
                'name',
                'categoryItems.id',
                [
                    'attribute' => 'items.description',
                    'format' => 'html',
                    'value' => 'description',
                ],
                [
                    'label'=>'Highlights',
                    'format'=>'raw',
                    'value'=>function($data) use ($model) {
                        if(TagFeaturedItem::find()->where(['item_id'=>$data->id, 'tag_id'=>$model->id])->all()) {
                            return Html::a('Remove as Highlighted', ['/highlights/category/'.$model->id.'/remove/'.$data->id], ['class'=>'btn btn-xs btn-danger']);
                        } else {
                            return Html::a('Add as Highlighted',['/highlights/category/'.$model->id.'/add/'.$data->id], ['class'=>'btn btn-xs btn-primary']);
                        }
                    },
                ],
            ],
        ]); ?>
    </div>
</div>

通常,视图文件是试图找到解决方案的混合搭配。 TagFeaturedItem 模型来自以前版本的视图,请参阅here

【问题讨论】:

  • 能否也给我们看一下视图文件?
  • 谢谢。整个事情不会导致错误?您只想访问功能标志?我看到另一个类 TagFeaturedItem...
  • 是的,我可以通过$category-&gt;items 关系获取类别项目,但featured 列当然不见了。
  • 啊,对不起,对我来说太难了...想知道为什么 'categoryItems.id' 和 'items.description' 有效。为什么new ActiveDataProvider(['query' =&gt; $searchModel-&gt;search(['CategorySearch'=&gt;['id'=&gt;$id]]),]); 有效。查询不应该是 QueryInterface 实现吗?
  • 我想从头开始写这篇文章,因为我自己一直在努力关注互联网上流传的所有文章和建议。这类问题的文档很少/不存在,所以现在我正在寻找一个解决方案,我可以丢弃迄今为止编写的任何代码并实现一些可行的东西。

标签: activerecord yii2


【解决方案1】:

在我看来,您的项目中可能存在一些我不会探索的设计缺陷;关于如何将相关数据放入gridview的问题,我将归零。

您可以在 gridview 中创建一个自定义列,然后获取相关数据,您可以将类似这样的内容添加到您的 gridview 列数组中:

    [
            'label'=>'featured',
            'format'=>'raw',
            'value'=>function($data)
            {
                $categories = $data->categories; 

                $content = "";
                foreach($categories as $category)
                    $content .= $category->title."<br/>";

                return $content;
            }
    ],

请注意,$data 代表数据提供者返回的模型,在上面的示例中来自您的项目模型。

【讨论】:

  • 我非常有兴趣了解可能存在的设计缺陷(以修复和学习),请详细说明。此外,它没有获取麻烦的相关数据,它正在获取并显示连接表中的“特色”列..
  • @jimmy 你的控制器 actionCategory 有点奇怪。至少直到现在我还没有看到这种情况。通常,有一个 actionIndex 和 actionUpdate 方法。看起来,您已将它们组合成一个动作。
  • 我有这种方式来实现更扁平的 url 结构。我的网址应该类似于highlights/category,它应该映射到经典的category/indexhighlights/category/1,它应该映射到category/update/1。但我也有highlights/keyword。问题是,在这个项目中,对于特定客户,类别/关键字是相同的东西(以编程方式)并且具有相同的操作。所以我将它们合并到一个表中,其中一个标志区分类型。
  • @jimmy 当您已经拥有某个类别时,您也在使用 CategorySearch...
  • @jimmy 我想通常你会用 urlManager 规则解决这个问题。
猜你喜欢
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
相关资源
最近更新 更多