gridviewyii2crudgii

Yii2 GridView implement Filter and Sort for Values for related Table of foreign Table


I have 3 Tables:

CREATE TABLE tabCve
(
    intCveID INTEGER NOT NULL AUTO_INCREMENT,
    strNumber VARCHAR(20) NOT NULL,
    fltScore FLOAT(0),
    strDescription TEXT,
    datImported DATETIME NOT NULL DEFAULT NOW(),
    intCvePhaseID INTEGER,
    intCveTypeID INTEGER,
    PRIMARY KEY (intCveID),
    KEY (intCvePhaseID),
    KEY (intCveTypeID)

) ;


CREATE TABLE tabProgress
(
    intProgressID INTEGER NOT NULL AUTO_INCREMENT,
    intProgressCveID INTEGER NOT NULL,
    intProgressUserID INTEGER NOT NULL,
    intProgressStateID INTEGER NOT NULL,
    intProgressCategoryID INTEGER,
    datCreated DATETIME NOT NULL,
    PRIMARY KEY (intProgressID),
    KEY (intProgressCategoryID),
    KEY (intProgressCveID),
    KEY (intProgressStateID),
    KEY (intProgressUserID)

) ;

CREATE TABLE tabCategory
(
    intCategoryID INTEGER NOT NULL AUTO_INCREMENT,
    strCategory VARCHAR(50) NOT NULL,
    PRIMARY KEY (intCategoryID)

) ;

I have created a CRUD with Gii for tabCve. I was successfull in implementing filter and sort functions for fields in referenced tables like intCvePhaseID

Now I would like to implement this for tabCategory via tabProgress the relation between tabCve and tabProgress is 1 to 1.

How do I have to implement it in my SearchModel?

What I did so far:

In the Model:

public function getProgress()
{
    return $this->hasOne(TabProgress::className(),['intProgressCveID' => 'intCveID'])->with(['category']);
}   

public function getCategory()
{
    return $this->hasOne(TabCategory::className(),['intCategoryID' => 'intProgressCategoryID']);
}

In the SearchModel:

public function search($params) { $query = TabCve::find();

$dataProvider = new ActiveDataProvider([
    'query' => $query,
    'sort'=> ['defaultOrder' => ['strNumber' => 'DESC']],
]);

$query->select(["intCveID","strNumber","fltScore","strDescription","datImported","intCvePhaseID","intCveTypeID",'progress.intProgressCategoryID']);
$query->joinWith("phase");
$query->joinWith("type");
$query->joinWith("progress");
$query->Where(['not like', 'strDescription', '** RESERVED **%', false]);
$query->andWhere(['not like', 'strDescription', '** REJECT **%', false]);
//$query->andWhere(["intProgressID" => null]);

$this->load($params);

if (!$this->validate()) {
    // uncomment the following line if you do not want to return any records when validation fails
    // $query->where('0=1');
    return $dataProvider;
}

$query->andFilterWhere([
    'intCveID' => $this->intCveID,
    'fltScore' => $this->fltScore,
    'datImported' => $this->datImported,
]);

$query->andFilterWhere(['like', 'strNumber', $this->strNumber])
    ->andFilterWhere(['like', 'strDescription', $this->strDescription])
    ->andFilterWhere(['like','tabPhase.strPhase', $this->intCvePhaseID])
    ->andFilterWhere(['like','datImported',$this->datImported])
    ->andFilterWhere(['like','tabType.strType', $this->intCveTypeID])
    ->andFilterWhere(['like','tabProgress.tabCategory.strCategory', $this->intCveTypeID])
    ;
return $dataProvider;
}

How do I have to implement the fields in these lines:

$query->select(["intCveID","strNumber","fltScore","strDescription","datImported","intCvePhaseID","intCveTypeID",'progress.intProgressCategoryID']);

and:

->andFilterWhere(['like','tabProgress.tabCategory.strCategory', $this->intCveTypeID])

Solution

  • In your seachModel you need public var for filter ..

    not need select because this are provide by find.. and is better rearrange the code below

    $query->select(["intCveID","strNumber","fltScore","strDescription","datImported","intCvePhaseID","intCveTypeID",'progress.intProgressCategoryID']);
    $query->joinWith("phase");
    $query->joinWith("type");
    $query->joinWith("progress");
    $query->Where(['not like', 'strDescription', '** RESERVED **%', false]);
    $query->andWhere(['not like', 'strDescription', '** REJECT **%', false]);
    

    in another way like suggested in this doc

    http://www.yiiframework.com/wiki/621/filter-sort-by-calculated-related-fields-in-gridview-yii-2-0/

    http://www.yiiframework.com/wiki/653/displaying-sorting-and-filtering-model-relations-on-a-gridview/

    For

    ->andFilterWhere(['like','tabProgress.tabCategory.strCategory', 
            $this->intCveTypeID])
    

    the samples provide in the link above suggest the use of getter for retrieve the column you need and the use of this getter also in andFilterWhere

    this way :

    in your Model you already have a

    public function getCategory()
    {
        return $this->hasOne(TabCategory::className(),
         ['intCategoryID' =>   'intProgressCategoryID']);
    }
    

    then you can buil a getter for for strCategory

    public function getStr_category() {
        return $this->category->strCategory;
    }
    

    at this point you can retrieve the data in you modelSearch with

    ->andFilterWhere(['like','str_category', $this->intCveTypeID])