我有一个gridview,其中我显示了注册用户的纬度和范围之间的距离。经度(在他们的个人资料中设置)和gridview线的纬度&经度。我创建了一个帮助类,它给了我一个返回所述距离的功能 我的距离gridview是这样的:
[
'format'=>'raw',
'attribute'=>'distance (km)',
'value'=> function ($data) {
$latFrom = Yii::$app->user->identity->profile->city->latitude;
$longFrom = Yii::$app->user->identity->profile->city->longitude;
$latTo = $data->createdBy->profile->city->latitude;
$longTo = $data->createdBy->profile->city->longitude;
return GeoHelper::distance($latFrom, $longFrom, $latTo, $longTo);
},
],
我试图在gridview中添加距离排序,但似乎无法找到如何执行此操作。 我尝试将一个公共$ distance属性添加到搜索模型并将其设置为安全,然后添加
$dataProvider->sort->attributes['distance'] = [
'asc' => ['distance' => SORT_ASC],
'desc' => ['distance' => SORT_DESC],
];
但没有运气
有什么想法吗?
答案 0 :(得分:2)
当然这不是问题,可以轻松解决。
要排序的值是在PHP中计算的,但DB对这些值没有任何线索。正如@Sergei Beregov所说,你可以使用ArrayDataProvider
,是的,使用它可以实现的方式。但是,根据用户的数量,它可能非常昂贵(如果你有很多用户)
如果您的数据库支持Geo功能,我建议在DB本身中计算距离值。例如,在MySQL中,您可以使用ST_Distance()来计算两点之间的距离,并将其与Yii2中的ActiveRecord关系混合。我在我的博客Spatial relations in Yii2中使用地理功能编写了一个实验人员。对不起,这是俄语,但我希望它会有所帮助。
只要您可以计算数据库中的距离,就可以像'distance' => SORT_ASC
答案 1 :(得分:1)
感谢Yerke的帮助我解决了! 在Post模型中,我创建了一个新的查找函数
public static function findWithDistance()
{
$latitudeFrom = Yii::$app->user->identity->profile->city->latitude;
$longFrom = Yii::$app->user->identity->profile->city->longitude;
return parent::find()
->addSelect([
"post.*",
"round(6371 * acos( cos( radians(postcity.latitude) ) * cos( radians({$latitudeFrom}) ) * cos( radians({$longFrom}) - radians(postcity.longitude)) + sin(radians(postcity.latitude)) * sin( radians({$latitudeFrom})))) as distance",
])
->leftJoin('user', 'post.created_by = user.id')
->leftJoin('profile', 'user.id = profile.user_id')
->leftJoin('city postcity', 'profile.location = postcity.id');
}
如果用户已登录,我在PostSearch模型中调用:
public function search($params)
{
$query = (!Yii::$app->user->isGuest && Yii::$app->user->identity->profile->city!=null) ? Post::findWithDistance() : Post::find();
...
答案 2 :(得分:0)
在gridview列中,将属性定义为
'attribute'=>'distance (km)',
但在您的提供商中,您将其称为“距离”
$dataProvider->sort->attributes['distance']
尝试在gridview中设置列,如下所示:
'attribute'=>'distance',
如果您需要在标题中显示“km”,请设置列的“标签”属性。