php - 为 foreach() 提供的参数无效 - 尝试在 SearchModel 上进行查询时 - Yii2
问题描述
我试图为迷你地理定位系统制作搜索模型。每当我尝试通过直接调用 GeoData 模型对数据进行排序时,除非我们尝试排序,否则它会起作用。
但是当我们尝试使用 CustomMade SearchModel 时,它会发送:为 foreach() 提供的参数无效
这是搜索模型:
<?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;
}
}
控制器(注释的代码有效,但不允许我使用 GridView 也不允许过滤或排序:
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);
}
*/
}
任何建议将不胜感激!
解决方案
First your GeoDataSearch
search()
function should look like this:
public function search($params)
{
$query = GeoData::find();
$dataProvider = new ActiveDataProvider([
'query' => $query,
'sort' => [
'defaultOrder' => [
'created_at' => SORT_DESC,
]
]
]);
$this->load($params);
if (!$this->validate())
return $dataProvider;
$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;
}
Add a second function to GeoDataSearch
model:
/**
* @param int $creator_id ID of the creator
* @param mixed $params
* @return ActiveDataProvider
*/
public function searchByCreator($creator_id, $params)
{
// This will verify if the $params['GeoDataSearch'] index exists
if ( isset( $params['GeoDataSearch'] ) ) {
$params['GeoDataSearch']['created_by'] = $creator_id;
} else {
// Create the index if it doesn't exist
$params['GeoDataSearch'] = ['created_by' => $creator_id];
}
return $this->search($params);
}
Update your actionView
:
public function actionView($id)
{
$title = "Ver Historial";
$searchModel = new GeoDataSearch;
// The $id param is already receiving the $_GET['id']
$dataProvider = $searchModel->searchByCreator($id, Yii::$app->request->queryParams);
return $this->render(
'view',
[
'title' => $title,
'searchModel' => $searchModel,
'dataProvider' => $dataProvider
]);
}
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:
<?= $form->field($searchModel, 'speed')->textInput(); ?>
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 from Yii::$app->request->queryParams
:
[
'GeoDataSearch' => [
'speed' => '10.00'
]
]
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 on GeoDataSearch
. This is the way Yii2 builds params with their core form methods and affects the models load()
method, and the reason that the implementation on searchByCreator
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 existing search
method, force the created_by
attribute, all while keeping the other filters alive.
推荐阅读
- python - holoviz/param/panel:通过 python 回调更新 Str 或 HTML 窗格
- python - python 装饰器不接受函数的参数
- reactjs - 获取 laravel8 fortify、sanctum api 数据并在 react 中展示
- android - 错误的输出,但正确的方程式 - 使用用户输入的除法
- r - 在 R Studio 中对分组数据执行 Mann-Whitney (Wilcox) 测试?
- c# - 让物体以匀速滑行到鼠标 Unity C#
- java - 如何在 Android 中打印受 Auth0-JWT 保护的私有 API 端点 JSON 对象?
- java - 我正在尝试构建我的应用程序,但出现此错误:AAPT2 进程意外退出。错误输出
- mpi - 数据解包将在第 501 行读取文件 util/show_help.c 中缓冲区的末尾
- firebase - Firebase Facebook 个人资料图片 (photoURL) 显示标准 Facebook 个人资料图片