根据同一个表中设置的预定义工作半径查找最近的位置

时间:2016-11-17 14:54:50

标签: php mysql json laravel latitude-longitude

我试图在表格中找到预定义条目的最近位置。到目前为止,我使用的查询工作正常,并提供了相当准确的结果集。

工作原理是:1表包含管道工的预定义估算,用于设定特定价格范围的估算成本。但是,每个水管工都有自己的工作半径,可以与其他水管工不同。这是一个例子。

表:预定义报价

ID     NAME     PRICERANGE     ESTIMATED-COST     WORKING-RADIUS    LAT    LONG
1      JOHN     £500-£800          £560             20 MILES        51.50   -0.118

我当前的查询循环遍历完整的预定义报价表,并按距离最接近的顺序对结果进行排序。

        $quotes = Quote::all()->where('latitude', '!=', null)->where('longitude', '!=', null)->where('estCost', '!=', null);
        foreach ($quotes as $quote) {
        $tableName = "quotes";
        $origLat = 52.5002721395; // Customers lat
        $origLon = -1.98032029216; // Customers long
        $dist = 45; // This needs to be dynamic like:  $quote->working_radius
        $query = DB::select("SELECT id, latitude, longitude, estCost, working_radius, 3956 * 2 *
                              ASIN(SQRT( POWER(SIN(($origLat - latitude)*pi()/180/2),2)
                              +COS($origLat*pi()/180 )*COS(latitude*pi()/180)
                              *POWER(SIN(($origLon-longitude)*pi()/180/2),2)))
                              as distance FROM $tableName WHERE
                              longitude between ($origLon-$dist/cos(radians($origLat))*69)
                              and ($origLon+$dist/cos(radians($origLat))*69)
                              and latitude between ($origLat-($dist/69))
                              and ($origLat+($dist/69))
                              having distance < $dist ORDER BY distance limit 25");
    }
    $json = json_encode($query);
    $obj = json_decode($json, TRUE);
    for ($i = 0; $i < count($obj); $i++) {
        echo "Distance is " . round($obj[$i]["distance"], 1) . " from est id:" . $obj[$i]["id"] . " <br />";
    }

我遇到的问题是查询使用变量$dist来定义管道工应该与客户纬度/长度的最大距离。除了我需要通过在同一个表或plumbers_profile表中设置的working_radius值来定义它之外,这是可以的。

我在这里使用laravel,我已经尝试了几种不同的方法来找到解决方案但似乎每次都失败了。

我可以解释这个问题的基本方法是,我需要选择所有预先定义的引号,这些引号在&#34; miles&#34;而不是在working_radius列中为每个管道工设置的值。

现在上面的查询将返回以下示例:

Distance is 4.4 from quote id:1617 

在理想的情况下,我需要分配$dist变量,如下所示:$quote->working_distance因为每个管道工的工作距离都不同,客户不应该显示预定义的报价单管道工未覆盖客户的位置。

如果我将$ quote-&gt; working_radius分配给$ dist变量,则结果不正确,如下所示:

Distance is 3.1 from quote id:1508 

然而,ID为1508的水管工只有2英里的work_radius,不应该显示。如果我设置$dist = 2;那么相同的管道工没有显示,那么问题在于动态分配$quote->working_radius并且无法使用数据库中设置的值来确定结果。

也许我会以完全错误的方式解决这个问题?作为一个学习者,我到目前为止一直努力,所以希望有更好经验的人可以提供帮助。感谢。

更新(2016年11月17日)

在发布我的问题之后处理代码后,我提出了一个有效的解决方案,但我不确定它是好还是坏!也许我已经过火了,也许我过于复杂的事情,假设这比实际需要的更复杂?

$quotes = Quote::orderBy('working_radius')->where('latitude', '!=', null)->where('longitude', '!=', null)->where('estCost', '!=', null)->get();

    $userLat = 52.5002721395; // Random selected lat and long for demo -- this acts as the customers property location
    $userLong = -1.98032029216;
    $tableName = "quotes";
    $dist = 250;  // This is the maximum it can be through the app
    $query = DB::select("SELECT id, working_radius, ( 3959 * acos( cos( radians($userLat) ) * cos( radians( latitude ) ) * cos( radians( longitude ) - radians($userLong) ) + sin( radians($userLat) ) * sin( radians( latitude ) ) ) )
            AS distance
            FROM $tableName
            HAVING distance < $dist
            ORDER BY distance LIMIT 0 , 25");
    $json = json_encode($query);
    $obj = json_decode($json, TRUE);
    for ($i = 0; $i < count($obj); $i++) {
        $plumbers[] = array('distance' => round($obj[$i]["distance"], 1), 'id' => $obj[$i]["id"], 'working_radius' => $obj[$i]["working_radius"]);
    }

    foreach ($plumbers as $plumber) {

        if($plumber['distance'] <= $plumber['working_radius']){
            var_dump($plumber);
        }
    }

希望我做了一半的事情吗?作为一个学习者,我在尝试自我教育的同时继续使用应用程序!感谢。

0 个答案:

没有答案