jimmy
jimmy

Reputation: 514

Yii2 get column from junction table and use in gridview

Part of my schema is a pictured:enter image description here

The junction table maps which items are in which category, with the "featured" column marking the item as featured in that category.

What I need to do is get a list of all items in a specific category, including the "featured" attribute from the junction table and pass that data for display into a gridview.

I have created a model for the category_item table and tried to implement the solution proposed here but how do I access and pass the data into the gridview?

Category Model

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

CategorySearch Model

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

Item Model

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

Controller

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.');
        }
    }
}

View

<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>

In general the view file is a mix and match from trying to find a solution. The TagFeaturedItem model is from a previous version of the view, see here

Upvotes: 3

Views: 3097

Answers (1)

dataskills
dataskills

Reputation: 656

In my opinion there may be some design flaws in your project that I will not explore; I will zero in on the question of how to get the related data into the gridview.

You can create a custom column in the gridview and then get the related data, you would add something like this to your gridview column array:

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

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

                return $content;
            }
    ],

Note that $data represents the model returned by the data provider, in the above example from your Item Model.

Upvotes: 1

Related Questions