Comment lier des paramètres à une requête de base de données brute dans Laravel qui est utilisé sur un modèle?
Re,
j'ai la requête suivante:
$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();
ça ne marche pas: Invalid parameter number: mixed named and positional parameters
.
est-ce que quelqu'un connaît une astuce ou une solution de contournement (je peux évidemment écrire la requête complète mais préfère utiliser le constructeur fluent).
6 réponses
OK, après quelques expériences, voici la solution que j'ai trouvé:
$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();
fondamentalement, setBindings
doit être appelé sur la requête. Ce voeu a été documenté!
Vieille question, mais si nous devons répéter une variable, nous devons changer sa valeur de clé dans les liaisons tableau.
$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]);
ça suffit.
pourquoi pas?
$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();
j'ai rencontré le même problème tout récemment et la réponse se trouve dans le message d'erreur mixed named and positional parameters
. Dans votre cas, les paramètres :lat
et :lng
sont nommés alors que vous avez $radius
comme position. Ainsi, une solution possible à votre problème est de faire usage de havingRaw()
et d'appliquer les paramètres nommés.
--havingRaw('distance < :radius', ['radius' => $radius])
$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();
j'ai porté la recherche à proximité de Doctrine v1 à Laravel, regardez ici.
il suffit d'ajouter le trait Geographical
au modèle alors vous pouvez faire:
$model->newDistanceQuery($request->query('lat'), $request->query('lon'))->orderBy('miles', 'asc')->get();
il fonctionne en utilisant selectRaw avec des fixations comme ceci:
$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]);
}