3

I am trying to modify the find() method inside the model search and it throws an error "The data provider property must be set".

Here is my search model:

public function search($params)
{

    $userID = Yii::$app->user->identity->id;

    $groups = GroupAccess::find()
    ->where(['user_id' => $userID, 'item_name' => 'group_creator'])
        ->asArray()
        ->all();
        foreach ($groups as $group) {
            $accessGroups[] = $group['group_id'];
        }

    $query = Group::find($accessGroups);

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

    $this->load($params);

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

    $query->andFilterWhere([
        'id' => $this->id,
        'status_id' => $this->status_id,
        //'created_user_id' => $this->created_user_id,
        'created_date' => $this->created_date,
        'profile_updated_user_id' => $this->profile_updated_user_id,
        'profile_updated_date' => $this->profile_updated_date,
        'last_accessed_user_id' => $this->last_accessed_user_id,
        'last_accessed_date' => $this->last_accessed_date,
    ]);

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

    return $dataProvider;
}

And here is my controller action:

$searchModel = new GroupSearch();
    $dataProvider =    $searchModel->search(Yii::$app->request->queryParams);

if (Yii::$app->request->isPjax) {
        return $this->renderAjax('groups', [
        'searchModel' => $searchModel,
        'dataProviderMine' => $dataProvider,
    ]);
    } else {
        return $this->render('groups', [
        'searchModel' => $searchModel,
        'dataProviderMine' => $dataProvider,
    ]);
    }

}

It is important to refine the query as the user should be able to see other groups.

How can i modify the find() method properly?

Thanks.

Mike Pearson
  • 505
  • 1
  • 6
  • 18

1 Answers1

2

I see two bugs here:

  1. Your find method

    $query = Group::find($accessGroups)

    will not work - just replace it with

    $query = Group::find()->where(['id' => $accessGroups]);
  2. I guess "The data provider property must be set" error is caused by your view code. E.g. if you are using GridView, you should set its 'dataProvider' widget option:

    GridView::widget([
        'dataProvider' => $dataProviderMine,
        'searchModel' => $searchModel,
        'columns' => [
            'id', 'status_id', 'created_date' // your view columns here
        ]
    ])
  3. Consider also using sub queries in your search method:

    $idAccessQuery = GroupAccess::find()
        ->where(['user_id' => $userID, 'item_name' => 'group_creator'])
        ->select('group_id');
    $query = Group::find()->where([
        'id' => $idAccessQuery
    ]);
arogachev
  • 33,150
  • 7
  • 114
  • 117
Pavel Bariev
  • 2,546
  • 1
  • 18
  • 21
  • So the sub-queries eliminates the need for the foreach loop right? Also, the idAccesQuery might return multiple id's. Is that a problem for the Group::find 'id' => array()? Thanks! – Mike Pearson Apr 18 '15 at 18:14
  • Correct. This will add a subquery to your sql with multiple group_id select from your GroupAccess db table. Notice that there will be no extra request do db - all in one query. – Pavel Bariev Apr 18 '15 at 18:20
  • Isn't there still two DB queries, one for the access table and one for the groups? – Mike Pearson Apr 18 '15 at 20:22
  • Forgive me, but how is there only one db action. There are two find() methods. – Mike Pearson Apr 19 '15 at 00:19
  • This is how it works: find method only returns ActiveQuery object which allows you to get plain sql from it - but it does not make request till you call one of its "fetch" methods ("one()", "all()", "column()" etc.). 'all()' method is called only from dataProvider here. So before that you can use a lot of ActiveQuery objects, joining them to the first one - and there will be only one sql request in the end. – Pavel Bariev Apr 19 '15 at 06:31