Yii2 Search model without using GridView

2019-08-10 20:55发布

问题:

There is a serch form on the mainpage of a realestate agency. The data about objects is stored in the table "realty" that uses relations. For example, there are related tables category (residential, commercial, land plots), deal (buy, sell, rent), object_type (apartment, house, office).

Then different categories have different properties and and there are three bootstrap tabs in the search form: residential, commercial, land plots. Under each tab there are selects and input fields that are specific for the choosen tab.

In the most cases, the examples of using Search model are given within a gridview. Is it possible to adapt Search model logic so that it could return the array of results from the table 'realty' based on the values indicated in the search form on the mainpage ?

回答1:

Yes, of course you can. you have several options:

Solution 1 - worst solution but the answer to your question

modify the search function of the model (or create a new function). The search functions usually looks like this

public function search($params)
{
    $query = Bookmark::find()->where('status <> "deleted"');
    $dataProvider = new ActiveDataProvider([
        'query' => $query,
        'pagination' => [
            'pageSize' => Yii::$app->session->get(get_parent_class($this) . 'Pagination'),
        ],
    ]);
    if (!($this->load($params) && $this->validate())) {
        return $dataProvider;
    }

    $query->andFilterWhere([
        'status' => $this->status,
        'id' => $this->id,
        'reminder' => $this->reminder,
        'order' => $this->order,
        'update_time' => $this->update_time,
        'update_by' => $this->update_by,
        'create_time' => $this->create_time,
        'create_by' => Yii::$app->user->id,
    ]);
    $query->andFilterWhere(['like', 'name', $this->name])
        ->andFilterWhere(['like', 'url', $this->url]);
    return $dataProvider;
}

You can change it to something like

public function search($params)
{
    $query = Bookmark::find()->where('status <> "deleted"');
    if (!($this->load($params) && $this->validate())) {
        THROW AN ERROR SOMEHOW HERE
    }

    $query->andFilterWhere([
        'status' => $this->status,
        'id' => $this->id,
        'reminder' => $this->reminder,
        'order' => $this->order,
        'update_time' => $this->update_time,
        'update_by' => $this->update_by,
        'create_time' => $this->create_time,
        'create_by' => Yii::$app->user->id,
    ]);
    $query->andFilterWhere(['like', 'name', $this->name])
        ->andFilterWhere(['like', 'url', $this->url]);
    return $query->all();

}

however this will return to you all the records because ActiveDataProvider takes care of the pagination based on the query given.

Solution 2, a better solution

read the first example here http://www.yiiframework.com/doc-2.0/yii-data-activedataprovider.html . You can call ->getModels() on an ActiveDataProvider to get the actual records. No changes needed to the search function. Do whatever you want with the array.

Solution 3 and what I use all the time

Use ActiveDataProvider with a ListView. The list view allows you to create the list of records however you want, it does not have to be a table. I personally do this in many places and it works quite well. I sometimes transform arrays to an ArrayDataProvider just to use it. More about data providers here: http://www.yiiframework.com/doc-2.0/guide-output-data-providers.html