Search code examples
phpmysqlyiiyii2many-to-many

Yii2 Many to Many with Self - filter through grid view (no attribute?)


I've used the Gii AJAX Crud generator, and I'm being driven up a wall by my own stupidity. I am using Yii 2 and want to search with many to many, on a table that has that relation with ITSELF in a junction table, with the Grid View.

table tag (id, name).

table tag_child (parent_id, child_id)


Class Tag
...
public function getParents()
{
    return $this->hasMany(self::className(), ['id' => 'child_id'])
        ->viaTable('tag_child', ['parent_id' => 'id']);
}

public function getChildren()
{
    return $this->hasMany(self::className(), ['id' => 'parent_id'])
        ->viaTable('tag_child', ['child_id' => 'id']);
}

And in my grid-view /columns:

    [
    'class' => '\kartik\grid\DataColumn',
    'attribute'=>'name',
],
[
    'class' => '\kartik\grid\DataColumn',
    'label' => 'Tag Type',
    'value' => function($tag) {
        return $tag->displayTagTypes();
    },
    'attribute' => 'tagTypes'
],


 TagQuery.php
 ...
 public $tagTypes;
        public function search($params)
 {
    $query = Tag::find();

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

    $this->load($params);

    if (!$this->validate()) {
        // $query->where('0=1');
        return $dataProvider;
    }

    $query->joinWith('parents p');

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

    $query->andFilterWhere(['like', 'tag.name', $this->name]);

    return $dataProvider;
}

I'm able to display the results in my index table with that value function, but my Tag filter isn't able to search by tagTypes. How do I populate that?

As an example, when it's not many to many, I can use set my attribute to 'joinedTableName.value' and it works as soon as I add a $query->orFilterWhere('like', 'parent.name', $this->id) or whatever. But I'm at a loss now...


Solution

  • Declare $searchModel = new TagQuery() in your controller, then pass the $searchModel to the view and include it in the GridView options as 'filterModel' => $searchModel.

    Either that, or you can do really custom filters using specific filterTypes and filter logic for each column.

    You declare public tagType in the query model, but you don't do anything with it. $query->andFilterWhere(['like', 'tag.name', $this->tagType]);