I'd like to do the following:
MyModel::where(MyModel::sql_distance_to(), ['lat' => '...', 'lng' => '...'])->get();
Where sql_distance_to()
returns some complex sql expression. But from what I can see, query builder doesn't support named bindings. Is this true? Any workaround?
答案 0 :(得分:1)
我相信你的意思是使用Query Scopes
class MyModel extends Model
{
public function scopeSqlDistanceTo($query, $lat, $lon)
{
// Previously DB::raw(expr) was here.
// No need since we're using whereRaw()
$whereRaw = 'lat = ? AND lon = ?';
return $query->whereRaw($whereRaw, [$lat, $lon]);
}
}
用法:
$latitude = 0.0;
$longitude = 180.0;
MyModel::sqlDistanceTo($latitude, $longitude)->get();
答案 1 :(得分:0)
tl; dr 如果可能,请使用Skysplit's solution。
这是我想出的。另一个复杂因素是默认情况下laravel disables pdo
的仿真模式。这导致无法在语句中多次使用同名的命名参数标记。
$q = MyModel::whereRaw(MyModel::sql_distance_to() . ' < :dist');
run_query_with_params(MyModel::class, $q,
array_merge(MyModel::sql_distance_to_params($lat, $lng), [
'dist' => 10,
]));
class MyModel {
static function sql_distance_to() {
return 'ACOS(
SIN(RADIANS(lat)) * SIN(RADIANS(:lat1))
+ COS(RADIANS(lat)) * COS(RADIANS(:lat2))
* COS(RADIANS(:lng - lng))
) * 6371';
}
static function sql_distance_to_params($lat, $lng) {
return [
'lat1' => $lat,
'lat2' => $lat,
'lng' => $lng,
];
}
}
function run_query_with_params($class, $q, $params)
{
$r = \DB::select($q->toSql(), $params);
return call_user_func([$class, 'hydrate'], $r);
}