如何使用laravel的查询构建器命名绑定?

问题描述:

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?

我想执行以下操作: p>

  MyModel  :: where(MyModel :: sql_distance_to(),['lat'=>'...','lng'=>'...']) - > get(); 
  code>   pre> 
 
 

其中 sql_distance_to() code>返回一些复杂的sql表达式。 但是从我所看到的,查询构建器不支持命名绑定。 这是真的? 任何解决方法? p> div>

I belive you mean using 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]);
    }
}

Usage:

$latitude = 0.0;
$longitude = 180.0;
MyModel::sqlDistanceTo($latitude, $longitude)->get();

tl;dr Use Skysplit's solution, if possible.

Here's what I came up with. One additional complication is that laravel by default disables pdo's emulation mode. Which results in being unable to use a named parameter marker of the same name more than once in a statement.

$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);
}