如何将参数绑定到模型上使用的 Laravel 中的原始数据库查询?
Posted
技术标签:
【中文标题】如何将参数绑定到模型上使用的 Laravel 中的原始数据库查询?【英文标题】:How to bind parameters to a raw DB query in Laravel that's used on a model? 【发布时间】:2014-01-18 20:00:55 【问题描述】:回复,
我有以下疑问:
$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();
它不起作用:Invalid parameter number: mixed named and positional parameters
。
有谁知道技巧或解决方法(我显然可以编写完整的查询,但更喜欢使用流利的构建器)。
【问题讨论】:
愚蠢的问题-但文档在其任何示例中都没有使用" "
。你试过单身吗?
@JamesBinford 是的,尝试了所有可能的组合,包括%s
您有 2 个:lat
在查询中,但只绑定了 1 个
@davidstrachan 似乎没有任何区别。
模型并不存在。您的意思是“在实例上使用”。模型只是一个空白模板。在 Laravel 世界中,每个人都使用了错误的术语,“模型”的意思是“实例”。
【参考方案1】:
好的,经过一些实验,这是我想出的解决方案:
$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();
基本上,setBindings
必须在查询中调用。希望这被记录在案!
【讨论】:
+1 正在寻找这个确切的答案...包括地图半径查询。谢谢! setBindings 似乎不支持 PDO 的命名参数:/ 如果您正在处理一个关系,例如,您应该使用addBinding
而不是setBindings
以避免覆盖关系绑定。
这是setBindings(array $bindings, $type = 'where')
的签名。如果您在 WHERE 子句中有绑定,那么这些将被覆盖。您应该指定您的绑定用于查询的 SELECT 部分。 ->setBindings([$lat, $lng, $lat, $radius], 'select')
对我也有用,虽然它不能很好地与 ->where() 一起使用,所以我也必须绑定它【参考方案2】:
老问题,但是如果我们必须重复一个变量,我们必须改变它在绑定数组中的键值。
$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]);
够了。
【讨论】:
拉阿姆。谢谢你,先生。 在哪个版本中可以将绑定作为 DB::raw 的第二个参数? 我在 Laravel 4.2 中使用它 在 4.2 中,您可以使用绑定作为 whereRaw() 中的第二个参数,但不能在 DB::raw() 中使用。在上面的示例中,绑定被传递给 select(),而不是 DB::raw()。 我收到一个错误“strtolower() 期望参数 1 是字符串,给定数组”【参考方案3】:为什么不呢?
$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();
【讨论】:
这是一个 2 年的问题。selectRaw
当时不可用。
select() 接受绑定【参考方案4】:
我最近遇到了同样的问题,答案在错误消息mixed named and positional parameters
中。在您的情况下,:lat
和 :lng
是命名参数,而 $radius
是位置参数。因此,解决您的问题的一种可能方法是使用 havingRaw()
并应用命名参数。
--havingRaw('distance < :radius', ['radius' => $radius])
【讨论】:
【参考方案5】:$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();
【讨论】:
【参考方案6】:我将附近的搜索从 Doctrine v1 移植到 Laravel,check it out here.
只需将 Geographical
特征添加到模型中即可:
$model->newDistanceQuery($request->query('lat'), $request->query('lon'))->orderBy('miles', 'asc')->get();
它通过使用 selectRaw 和这样的绑定来工作:
$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]);
【讨论】:
以上是关于如何将参数绑定到模型上使用的 Laravel 中的原始数据库查询?的主要内容,如果未能解决你的问题,请参考以下文章
如何更改绑定到 Razor 页面上模型的特定文本的字体颜色?
如何将参数传递到链式 Laravel Eloquent 关系中的位置
Laravel Livewire 绑定模型 Carbon 属性