I was trying to make a search model for a mini Geo location system. Whenever I tried to get the data sorted by directly calling the GeoData model it works unless we try to sort.
But when we try to use the CustomMade SearchModel it sends : Invalid argument supplied for foreach()
Here is the SearchModel:
<?php namespace app\models;
use Yii;
use yii\base\Model;
use yii\data\ActiveDataProvider;
use app\models\GeoData;
/**
* This is the ActiveQuery class for [[GeoData]].
*
* @see GeoData
*/
class GeoDataSearch extends GeoData
{
const TODOS = 1;
const FECHA = 2;
const ENVIADO_POR = 3;
public function rules()
{
return [
[['latitude', 'longitude'], 'required'],
[['latitude', 'longitude', 'accuracy', 'speed', 'betterlocation'], 'number'],
[['device_id', 'active', 'sended', 'mobildate', 'created_at', 'updated_at', 'created_by'], 'integer'],
[['created_by'], 'exist', 'skipOnError' => true, 'targetClass' => User::class, 'targetAttribute' => ['created_by' => 'id']],
];
}
/*public function active()
{
return $this->andWhere('[[status]]=1');
}*/
public function scenarios()
{
return Model::scenarios();
}
public function search($params)
{
$query = GeoData::find()->where(['created_by' => $params])->all();
$dataProvider = new ActiveDataProvider([
'query' => $query,
'sort' => [
'defaultOrder' => [
'created_at' => SORT_DESC,
]
]
]);
$dataProvider->sort->attributes['created_at'] = [
'asc' => ['created_at' => SORT_ASC],
'desc' => ['created_at' => SORT_DESC]
];
$dataProvider->sort->attributes['created_by'] = [
'asc' => ['created_by' => SORT_ASC],
'desc' => ['created_by' => SORT_DESC]
];
$dataProvider->sort->attributes['geo_id'] = [
'asc' => ['geo_id' => SORT_ASC],
'desc' => ['geo_id' => SORT_DESC]
];
$this->load($params);
$query->andFilterWhere([
'geo_id' => $this->geo_id,
'latitude' => $this->latitude,
'longitude' => $this->longitude,
'accuracy' => $this->accuracy,
'speed' => $this->speed,
'device_id' => $this->device_id,
'betterlocation' => $this->betterlocation,
'active' => $this->active,
'mobiledate' => $this->mobildate,
'sended' => $this->sended,
'updated_at' => $this->updated_at,
'created_at' => $this->created_at,
'created_by' => $this->created_by,
]);
return $dataProvider;
}
}
And the controller (The code that is commented works but it won't allow me to use the GridView nor filter or Sort:
public function actionView($id)
{
$title = "Ver Historial";
$id = $_GET['id'];
$searchModel = new GeoDataSearch;
$dataProvider = $searchModel->search($id);
return $this->render(
'view',
[
'title' => $title,
'searchModel' => $searchModel,
'dataProvider' => $dataProvider
]);
/*
if (Yii::$app->user->can(AuthItem::ROLE_ADMINISTRATOR))
{
$id = $_GET['id'];
$title = "Ver Historial";
$model = new GeoData;
$dataProvider = $model::findAll(['created_by'=> $id]);
return $this->render(
'view',
[
'title' => $title,
'dataProvider' => $dataProvider,
]
);
} else {
throw new ForbiddenHttpException('Access denied for user '.Yii::$app->user->identity->id);
}
*/
}
Any Suggestion will be really appreciated!
First your
GeoDataSearch
search()
function should look like this:Add a second function to
GeoDataSearch
model:Update your
actionView
:Don't setup user validation in the
actionView
, use AccessControl instead.Explaining
DataProvider are for easy data pagination and sorting (View docs).
Querys filters the data for the DataProvider manipulation.
The
search
method is a convention for attaching query filters to a DataProvider in a single place for better reuse. So you should be looking to have a generic search method that can be reused on multiple scenarios.In this example, the
GeoDataSearch->search()
method is used for searching multiple GeoData models by passing any parameter you want, so you will pass an array to it, most likely with the data from front-end.If you are using Yii2 ActiveForm inputs (with GET method set) in your front-end, on
GeoDataSearch
fields. For example:This will allow to filter the results by the
speed
attribute. When a user submit this form, your back-end will get the following content fromYii::$app->request->queryParams
:You should use this on the
search
method, that will filter all GeoData by their speed.Important to notice that the
speed
attribute will be a index onGeoDataSearch
. This is the way Yii2 builds params with their core form methods and affects the modelsload()
method, and the reason that the implementation onsearchByCreator
seems a little convoluted.Back to your case,
You need to filter by the creator. Since this needs to always be attached to the search query params, I recommend you to create a new method (
searchByCreator
), which consumes the already existingsearch
method, force thecreated_by
attribute, all while keeping the other filters alive.