it-swarm.com.de

Wie binden Sie Parameter an eine unformatierte DB-Abfrage in Laravel, die für ein Modell verwendet wird?

Re,

Ich habe folgende Frage:

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

Es funktioniert nicht: Invalid parameter number: mixed named and positional parameters.

Kennt jemand einen Trick oder eine Problemumgehung (ich kann natürlich die vollständige Abfrage schreiben, aber lieber den fließenden Builder verwenden).

42
MarkL

OK, nach einigen Experimenten, hier ist die Lösung, die ich gefunden habe:

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

Grundsätzlich muss setBindings für die Abfrage aufgerufen werden. Ich wünschte das wäre dokumentiert!

83
MarkL

Alte Frage, aber wenn wir eine Variable wiederholen müssen, müssen wir ihren Schlüsselwert im Bindings-Array ändern.

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

Das ist genug.

22
bluesky777

warum nicht?

    $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();
10
Stefan Z

Ich habe vor kurzem dasselbe Problem festgestellt und die Antwort befindet sich in dieser Fehlermeldung mixed named and positional parameters. In Ihrem Fall sind :lat und :lng benannte Parameter, während Sie $radius als Position haben. Eine mögliche Lösung für Ihr Problem ist die Verwendung von havingRaw() und das Anwenden von benannten Parametern. 

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

2
jovani

Ich habe die nahegelegene Suche von Doctrine v1 nach Laravel portiert, check hier.

Fügen Sie dem Modell einfach die Geographical-Eigenschaft hinzu. Dann können Sie Folgendes tun:

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

Es funktioniert mit selectRaw mit Bindungen wie folgt:

$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
malhal
$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
Danilo Lima