How to bind parameters to a raw DB query in Laravel that's used on a model?

后端 未结 6 546
迷失自我
迷失自我 2020-11-29 01:41

Re,

I have the following query:

$property = 
    Property::select(
        DB::raw(\"title, lat, lng, ( 
            3959 * acos( 
                co         


        
相关标签:
6条回答
  • 2020-11-29 02:16
    $select = <<<SQL
        title,
        lat,
        lng,
        (3959*acos(cos(radians( ? ))*cos(radians(lat))*cos(radians(lng)-radians( ? ))+sin(radians( ? ))*sin(radians(lat)))) AS distance
    SQL;
    
    $property = Property::selectRaw($select, [$lat, $lng, $lat])
        ->having('distance', '<', $radius)
        ->orderBy('distance')
        ->take(20)->get();
    
    0 讨论(0)
  • 2020-11-29 02:18

    I ported the nearby search from Doctrine v1 to Laravel, check it out here.

    Just add the Geographical trait to the model then you can do:

    $model->newDistanceQuery($request->query('lat'), $request->query('lon'))->orderBy('miles', 'asc')->get();
    

    It works by using selectRaw with bindings like this:

    $sql = "((ACOS(SIN(? * PI() / 180) * SIN(" . $latName . " * PI() / 180) + COS(? * PI() / 180) * COS(" . $latName . " * PI() / 180) * COS((? - " . $lonName . ") * PI() / 180)) * 180 / PI()) * 60 * ?) as " . $unit;
    if($kilometers){
        $query->selectRaw($sql, [$lat, $lat, $lon, 1.1515 * 1.609344]);
    }
    else{
        // miles
        $query->selectRaw($sql, [$lat, $lat, $lon, 1.1515]);
    }
    
    0 讨论(0)
  • 2020-11-29 02:19

    why not?

        $latitude = $request->input('latitude', '44.4562319000');
        $longitude = $request->input('longitude', '26.1003480000');
        $radius = 1000000;
    
        $locations = Locations::selectRaw("id, name, address, latitude, longitude, image_path, rating, city_id, created_at, active,
                             ( 6371 * acos( cos( radians(?) ) *
                               cos( radians( latitude ) )
                               * cos( radians( longitude ) - radians(?)
                               ) + sin( radians(?) ) *
                               sin( radians( latitude ) ) )
                             ) AS distance", [$latitude, $longitude, $latitude])
            ->where('active', '1')
            ->having("distance", "<", $radius)
            ->orderBy("distance")
            ->get();
    
    0 讨论(0)
  • 2020-11-29 02:26

    I encountered same issue just recently and the answer is in that error message mixed named and positional parameters. In your case, the :lat and :lng are named parameters while you have $radius as positional. So one possible fix to your issue is make use of havingRaw() and apply named parameters.

    --havingRaw('distance < :radius', ['radius' => $radius])

    0 讨论(0)
  • 2020-11-29 02:28

    Old question, but if we have to repeat a variable, we have to change its key value in the bindings array.

        $property = Property::select(
            DB::raw("title, lat, lng, ( 3959 * acos( cos( radians(:lat) ) * 
            cos( radians( lat ) ) * cos( radians( lng ) - radians(:lng) ) + 
            sin(radians(:lat_i) ) * sin( radians( lat ) ) ) ) AS distance"),
            ["lat" => $lat, "lng" => $lng, "lat_i" => $lat]);
    

    That's enough.

    0 讨论(0)
  • 2020-11-29 02:35

    OK, after some experimenting, here's the solution that I came up with:

    $property = 
        Property::select(
            DB::raw("title, lat, lng, ( 
                3959 * acos( 
                    cos( radians(  ?  ) ) *
                    cos( radians( lat ) ) * 
                    cos( radians( lng ) - radians(?) ) + 
                    sin( radians(  ?  ) ) *
                    sin( radians( lat ) ) 
                )
           ) AS distance")
        )
        ->having("distance", "<", "?")
        ->orderBy("distance")
        ->take(20)
        ->setBindings([$lat, $lng, $lat,  $radius])
        ->get();
    

    Basically, setBindings has to be called on the query. Wish this was documented!

    0 讨论(0)
提交回复
热议问题