按经纬度排序

Order by latitude and longitude

我正在开发一个用于 post 广告的项目,该项目基于本地化,因此当用户 post 他的广告应用程序检测他的位置时,当其他人对他的广告感兴趣时他们可以在地图上找到他。问题是我想使用广告的纬度和经度以及使用该应用程序的人的经纬度从最近的广告到最远的广告排序

public function get_searched(Request $request){
    $annonce =DB::table('annonces')
    ->where('nomAnnonce','like','%'.$request->input("nomAnnonce").'%')
    ->orderby(((('latitude'- $request->input("lat"))*('latitude'-$request->input("lat"))) + (('longitude' - $request->input("lon"))*('longitude' - $request->input("lon")))), 'ASC')
    ->get();
    echo $annonce;}

这就是我所能做的,但结果是错误的:

SQLSTATE[42S22]: Column not found: 1054 Champ '1359.309643206' inconnu dans 
order clause (SQL: select * from `annonces` where `nomAnnonce` like %P% 
order by `1359`.`309643206` asc)

如果有人能提供帮助,那将是我的荣幸

public function get_searched(Request $request){
    $annonce =DB::table('annonces')
    ->select('*', 
    DB::raw(((('latitude'- $request->input("lat"))*('latitude'-$request->input("lat"))) + (('longitude' - $request->input("lon"))*('longitude' - $request->input("lon")))) 
            as 'distance'
            )
    ->where('nomAnnonce','like','%'.$request->input("nomAnnonce").'%')
    ->orderby('distance', 'ASC')
    ->get();
    echo $annonce;}

碰巧,我从事过一些做非常相似事情的项目,并将一些可以提供帮助的辅助函数放在一起。有一种算法可以计算两组坐标之间的距离,因此这些助手会为您执行该算法,或者生成在数据库中执行它所必需的 SQL。 distance_sql() 听起来像您要查找的内容。通过让查询而不是脚本来完成工作,您有机会在结果集返回之前对其进行排序和分页。我建议在调用它的模型中放置一个 query-scope 方法。

如果您还没有这样做,请创建一个 app/helpers.php 文件并将其添加到您的 composer.json 文件,然后 运行 composer install:

"autoload": {
    "files": [
        "app/helpers.php",
        ...
    ],
    ...
},
...

最后,将这些放入您的 helpers.php:

if (!function_exists('distance')) {
    /**
     * Calculate the distance between two sets of coordinates
     *
     * @param float $latitude1
     * @param float $longitude1
     * @param float $latitude2
     * @param float $longitude2
     * @param float $padding
     * @return float
     */
    function distance($latitude1, $longitude1, $latitude2, $longitude2, $padding = 0.0)
    {
        $earthRadiusInMiles = 3959;

        $latitude1 = deg2rad($latitude1);
        $latitude2 = deg2rad($latitude2);
        $longitude1 = deg2rad($longitude1);
        $longitude2 = deg2rad($longitude2);

        $miles = $earthRadiusInMiles * acos(
            cos($latitude1) * cos($latitude2)
            * cos($longitude2 - $longitude1)
            + sin($latitude1) * sin($latitude2)
        );

        $miles += $padding * $miles;

        return round($miles, 3);
    }
}

if (!function_exists('distance_sql')) {
    /**
     * Generate the SQL needed to calculate the distance between two sets of coordinates
     *
     * @param float|string $latitude1
     * @param float|string $longitude1
     * @param float|string $latitude2
     * @param float|string $longitude2
     * @param float $padding
     * @return string
     */
    function distance_sql($latitude1, $longitude1, $latitude2, $longitude2, $padding = 0.0)
    {
        $earthRadiusInMiles = 3959;

        $latitude1 = 'RADIANS('.DB::connection()->getPdo()->quote($latitude1).')';
        $latitude2 = "RADIANS($latitude2)";
        $longitude1 = 'RADIANS('.DB::connection()->getPdo()->quote($longitude1).')';
        $longitude2 = "RADIANS($longitude2)";

        $sql = "$earthRadiusInMiles * ACOS("
            . "COS($latitude1) * COS($latitude2)"
            . " * COS($longitude2 - $longitude1)"
            . " + SIN($latitude1) * SIN($latitude2))";

        $sql .= " + $padding * $sql";

        return $sql;
    }
}

试试这个:

public function get_searched(Request $request){
    $annonces = DB::table("annonces")
    ->where('nomAnnonce','like','%'.$request->input("nomAnnonce").'%')
    ->orderBy(DB::raw("3959 * acos( cos( radians({$request->input('lat')}) ) * cos( radians( latitude ) ) * cos( radians( longitude ) - radians(-{$request->input('lon')}) ) + sin( radians({$request->input('lat')}) ) * sin(radians(latitude)) )"), 'ASC')
    ->get()
    dd($annonces);
}

这种方法使用余弦球面定律来获得距离