2017-05-31 105 views
2

我在我的模型中創建了一個範圍,它創建一個別名,我需要執行它的位置,我明白MySql不允許這樣做。在Laravel中計算座標距離

標準SQL不允許您引用WHERE 子句中的列別名。施加此限制是因爲當執行WHERE代碼 時,列值可能尚未確定。

但是,我想知道是否有可能laravel工作? 我的範圍創建一個別名距離,我想檢查距離。

public static function scopeDistance($query, $lat, $long) 
{ 
    return $query->select(array('*',\DB::raw('(3959 * acos(cos(radians(' . $lat . ')) * cos(radians(latitude)) * cos(radians(longitude) - radians(' . $long . ')) + sin(radians(' . $lat .')) * sin(radians(latitude)))) AS distance'))); 
} 

在我的控制器:

\App\Profile::distance($latitude, $longitude)->where('distance', '<', 50); 

回答

3

首先,不要忘記在函數調用神奇靜態看Profile::distance呼叫刪除static關鍵字,Laravel交易。

以下是解決相同問題的兩種不同選項,無論哪種情況,您都可以從控制器中撥打\App\Profile::distance($latitude, $longitude, 50)

選項1

你可以做計算的內存,而不是處理子查詢。

public function scopeDistance($query, $lat, $long, $distance) { 
    return Profile::all()->filter(function ($profile) use ($lat, $long, $distance) { 
     $actual = 3959 * acos(
      cos(deg2rad($lat)) * cos(deg2rad($profile->latitude)) 
      * cos(deg2rad($profile->longitude) - deg2rad($long)) 
      + sin(deg2rad($lat)) * sin(deg2rad($profile->latitude)) 
     ); 
     return $distance < $actual; 
    }); 
} 

選項2

可以執行一個SQL子查詢,確保結束與get()電話:

public function scopeDistance($query, $lat, $long, $distance) { 
    return $query->having('distance', '<', $distance) 
      ->select(DB::raw("*, 
        (3959 * ACOS(COS(RADIANS($lat)) 
          * COS(RADIANS(latitude)) 
          * COS(RADIANS($long) - RADIANS(longitude)) 
          + SIN(RADIANS($lat)) 
          * SIN(RADIANS(latitude)))) AS distance") 
      )->orderBy('distance', 'asc') 
       ->get(); 
}