Yii2:选择距离并映射到模型

Yii2: Selecting distance and mapping to model

在我的 ProjectController 中,我得到了以下函数:

public function actionFindNearest($latitude, $longitude, $amount){
    $projects = Project::findNearest($latitude, $longitude, $amount);
    $html = '';
    foreach($projects as $project){
        $html .= $this->renderPartial( '/project/preview', array('model'=>$project), true );
    }
    return $html;
}

模型中的方法如下所示:

public static function findNearest($latitute, $longitude, $amount){
    $sql = 'SELECT SQRT(
            POW(69.1 * (latitude - '.$latitute.'), 2) +
            POW(69.1 * ('.$longitude.' - longitude) * COS(latitude / 57.3), 2)) AS distance, p.*
            FROM project as p
            ORDER BY distance LIMIT '.$amount;

    $command = Yii::$app->db->createCommand($sql);
    return $command->queryAll();
}

我现在得到的是一个包含 3 个对象的数组,其中包含所有模型属性以及我想要的距离 - 完美! 在控制器中,我现在将它传递给 renderPartial:

foreach($projects as $project){
        $html .= $this->renderPartial( '/project/preview', array('model'=>$project), true );
    }

在 preview.php 模板中,距离属性丢失了,因为现在我只有模型对象,其中距离不是官方字段。

编辑:项目的模型属性class:

/**
 * This is the model class for table "project".
 *
 * @property integer $id
 * @property string $updated
 * @property string $name
 * @property string $description
 * @property string $teaserimage
 * @property string $goal
 * @property string $current
 * @property string $startdate
 * @property string $enddate
 * @property string $created
 * @property string $headerimage
 * @property integer $category_id
 * @property integer $address_id
 * @property integer $user_id
 * @property string $website_url
 *
 * @property Comment[] $comments
 * @property Donation[] $donations
 * @property Goodie[] $goodies
 * @property Address $address
 * @property Category $category
 * @property User $user
 */

我怎样才能在我的模板文件中使用距离?

感谢您的建议!

您需要将 public $distance 属性 添加到您的项目模型中,然后它会自动填充每条记录

我做了类似的事情,例如,如果你想从 table 中获取 10 公里范围内的所有记录。方法是先计算边界minLat, maxLat, minLng, maxLng,然后过滤记录,只得到进入正方形的记录,然后计算距离(只针对这条记录,不针对整个table)有两个目的:

  • 首先排除在正方形(minLat,maxLat,minLong,maxLong)内但不在圆内($MyLocation,5 km)的记录。
  • 其次,获取每条记录的距离,并根据距离进行排序。

我认为这是最好的方法,请参考这篇文章 https://www.mullie.eu/geographic-searches/

请注意引擎在 "select" 之前执行 "where" 子句。

不要忘记将属性 "distance" 添加到您的模型,并将其添加到重写方法 "fields"。

class WoPdv extends \yii\db\ActiveRecord{

   public $distance='';
   ...

   public function fields() {

    $fields=parent::fields();

   // unset($fields['distance']);
    $fields[]= "distance";

    return $fields;
   }
   ...
    }

在控制器中

       $range = 10;// km
    // earth's radius in km = ~6371
        $radius = 6371;

        $maxlat = $lat + rad2deg($range / $radius);
        $minlat = $lat - rad2deg($range / $radius);

        $maxlng = $lng + rad2deg($range / $radius / cos(deg2rad($lat)));
        $minlng = $lng - rad2deg($range / $radius / cos(deg2rad($lat)));

        $q = WoPdv::find()->where(['between', 'wo_pdvLat', $minlat, $maxlat])->andWhere(['between', 'wo_pdvLong', $minlng, $maxlng]);

        $q->select(['*',"ROUND((((acos(sin((".$lat."*pi()/180)) * sin((`wo_pdvLat`*pi()/180))+cos((".$lat."*pi()/180)) * cos((`wo_pdvLat`*pi()/180)) * cos(((".$lng."- `wo_pdvLong`)*pi()/180))))*180/pi())*60*1.1515*1.609344),2) as distance"]);//distance in km 
        $q->having('distance <='.$range);
        $q->orderBy('distance');       
     // echo $q->createCommand()->getRawSql();die();
        $POSlist=$q->all();