我有一个有效的 laravel select 查询。我如何添加过滤器?
I have a working laravel select query. how do i add filters?
大家好吗?提前致谢。
我在 laravel 模型中编写了一个工作函数,该模型执行地理搜索和 returns 按距离搜索的顺序。效果很好。
public static function searchByDistance($distance, $unit)
{
//spatial queries
// $circle_radius = 6371;
$circle_radius = 3959;
$max_distance = $distance;
$lat = Auth::user()->getLoc()->latitude;
$lng = Auth::user()->getLoc()->longitude;
//get all nearby places
$nearbyusers = DB::select(
'SELECT * FROM
(SELECT users.id, users.country, places.name, places.state_code, places.latitude, places.longitude, (' . $circle_radius . ' * acos(cos(radians(' . $lat . ')) * cos(radians(latitude)) *
cos(radians(longitude) - radians(' . $lng . ')) +
sin(radians(' . $lat . ')) * sin(radians(latitude))))
AS distance
FROM users
LEFT JOIN places ON users.suburb=places.name) AS distances
WHERE distance < ' . $max_distance . '
ORDER BY distance;
');
$nearbyusers = (object)$nearbyusers;
return $nearbyusers;
}
但是我有一个问题。我想调用该函数,return 查询并继续能够对其进行 add ->where()
操作,直到我准备好使用 get()
和 return 结果。
我不能使用 where() or get()
我知道为什么。它的格式不正确。
有没有人可以帮助我 modify/alter 这个功能,这样我就可以在 return $nearbyusers
值后添加更多过滤器?
干杯
看看 official documentation for raw expressions 我想这就是您要找的。无论如何,您必须将原始查询更改为 "builded" 查询,如下所示:
$nearbyusersquery = DB::table('users')
->select(DB::RAW('SELECT users.id, users.country, places.name, places.state_code, places.latitude, places.longitude, (' . $circle_radius . ' * acos(cos(radians(' . $lat . ')) * cos(radians(latitude)) *
cos(radians(longitude) - radians(' . $lng . ')) +
sin(radians(' . $lat . ')) * sin(radians(latitude))))
AS distance'))
->leftJoin('places', 'users.suburb', '=', 'places.name')
->where('distance', '<', $max_distance)
->orderBy('distance');
return $nearbyusersquery
通过这种方式,您的方法将 return 一个可以与其他语句链接的 Builder
对象。
您将要查看底层的 Fluent 查询构建器系统。就目前而言,您的查询是独立的。也有可能这个特定的人可能需要保持独立。
为了以您想要的方式连接到 Fluent,您需要传入查询(这应该会自动解析),添加到其中,然后 return 查询。关于您当前的功能,这可能需要与您所拥有的完全不同的方法(尽管您所拥有的是您希望最终得到的查询的良好模型)。
查看 the docs about query scopes, which may be addressing how you're trying to integrate it. Also, have a look at the code itself, such as this one for the JoinClause function,了解如何构建代码。
基本元素是您需要获取的元素和 return 查询对象。这意味着它不能是静态方法(它需要对象实例),并且根据您采用的方法,您将 returning 传入 $query
对象(范围) 或 $this
(它们模型对象的实例本身)。
您需要找到一种方法将您的查询封装到您需要的部分中。它可能是这样的:
public function byDistance($distance, $unit) {
$lat = Auth::user()->getLoc()->latitude;
$lng = Auth::user()->getLoc()->longitude;
return $this->join(DB::select('SELECT users.id, users.country, places.name, places.state_code, places.latitude, places.longitude, (' . $circle_radius . ' * acos(cos(radians(' . $lat . ')) * cos(radians(latitude)) *
cos(radians(longitude) - radians(' . $lng . ')) +
sin(radians(' . $lat . ')) * sin(radians(latitude)))
AS distance'),
'users.id', 'distance.user_id = users.id')
->leftJoin('places', 'users.suburb = places.name')
->where('distance', '<', $distance)
->orderBy('distance');
}
请注意查询构建部分中缺少实际的 select
(尽管有嵌套的 select),并且缺少任何类型的实际提取。它所做的是添加到当前查询中,然后在最终调用 get
或其他获取函数时构建该查询。这为您提供了一个较大查询的离散片段,您可以在调用它时将其添加到其中。
您也可以使用 sql 来完成。例如:
$filtr = "";
$filtr2 = "";
If (something)
$filtr =" and field = var";
If (somethingelse)
$filtr2 = " and field2 = other_var";
// this can be in the elloquent query
$query = "select ....
from ....
Where 1=1
$filtr
$filtr2
";
编辑
//assuming the country Id is passed to your controller
// first initialize the filter as empty string
$countryFilter = "";
// if the country is not null or empty replace the filter
if ($country != null && $country != "")
$countryFilter = "and country = $countryFilter";
$nearbyusers = DB::select(
'SELECT * FROM
(SELECT users.id, users.country, places.name, places.state_code, places.latitude, places.longitude, (' . $circle_radius . ' * acos(cos(radians(' . $lat . ')) * cos(radians(latitude)) *
cos(radians(longitude) - radians(' . $lng . ')) +
sin(radians(' . $lat . ')) * sin(radians(latitude))))
AS distance
FROM users
LEFT JOIN places ON users.suburb=places.name) AS distances
WHERE distance < ' . $max_distance . '
-- if no country was selected then it will just be an empty line
$countryFilter
ORDER BY distance;
');
嗯,还是老样子,自己解决了。问题很简单。您所要做的就是查找与结果匹配的用户对象并将它们推入数组。然后return那个数组,你就可以使用函数了!所以如果你想从原始查询中获取可传递的对象,这就是你要做的。再次感谢你们提供有用的答案。这个问题真的很简单。最后我摆弄它来工作,而不是从互联网上得到任何答案。
//spatial queries
$circle_radius = 6371;
// $circle_radius = 3959;
$max_distance = request('distance');
$lat = Auth::user()->getLoc()->latitude;
$lng = Auth::user()->getLoc()->longitude;
//get all nearby places
$nearbyusers = DB::select(
'SELECT * FROM
(SELECT users.id, users.country, places.name, places.state_code, places.latitude, places.longitude, (' . $circle_radius . ' * acos(cos(radians(' . $lat . ')) * cos(radians(latitude)) *
cos(radians(longitude) - radians(' . $lng . ')) +
sin(radians(' . $lat . ')) * sin(radians(latitude))))
AS distance
FROM users
LEFT JOIN places ON users.suburb=places.name) AS distances
WHERE distance < ' . $max_distance . '
ORDER BY distance;
');
$users = [];
foreach($nearbyusers as $user)
{
array_push($users, User::where('id', $user->id)->first());
}
//$nearbyusers = (object)$nearbyusers;
return Response::json( array(
'searchsuccess' => (String) view('members.yessearch', compact('users'))
) );
大家好吗?提前致谢。
我在 laravel 模型中编写了一个工作函数,该模型执行地理搜索和 returns 按距离搜索的顺序。效果很好。
public static function searchByDistance($distance, $unit)
{
//spatial queries
// $circle_radius = 6371;
$circle_radius = 3959;
$max_distance = $distance;
$lat = Auth::user()->getLoc()->latitude;
$lng = Auth::user()->getLoc()->longitude;
//get all nearby places
$nearbyusers = DB::select(
'SELECT * FROM
(SELECT users.id, users.country, places.name, places.state_code, places.latitude, places.longitude, (' . $circle_radius . ' * acos(cos(radians(' . $lat . ')) * cos(radians(latitude)) *
cos(radians(longitude) - radians(' . $lng . ')) +
sin(radians(' . $lat . ')) * sin(radians(latitude))))
AS distance
FROM users
LEFT JOIN places ON users.suburb=places.name) AS distances
WHERE distance < ' . $max_distance . '
ORDER BY distance;
');
$nearbyusers = (object)$nearbyusers;
return $nearbyusers;
}
但是我有一个问题。我想调用该函数,return 查询并继续能够对其进行 add ->where()
操作,直到我准备好使用 get()
和 return 结果。
我不能使用 where() or get()
我知道为什么。它的格式不正确。
有没有人可以帮助我 modify/alter 这个功能,这样我就可以在 return $nearbyusers
值后添加更多过滤器?
干杯
看看 official documentation for raw expressions 我想这就是您要找的。无论如何,您必须将原始查询更改为 "builded" 查询,如下所示:
$nearbyusersquery = DB::table('users')
->select(DB::RAW('SELECT users.id, users.country, places.name, places.state_code, places.latitude, places.longitude, (' . $circle_radius . ' * acos(cos(radians(' . $lat . ')) * cos(radians(latitude)) *
cos(radians(longitude) - radians(' . $lng . ')) +
sin(radians(' . $lat . ')) * sin(radians(latitude))))
AS distance'))
->leftJoin('places', 'users.suburb', '=', 'places.name')
->where('distance', '<', $max_distance)
->orderBy('distance');
return $nearbyusersquery
通过这种方式,您的方法将 return 一个可以与其他语句链接的 Builder
对象。
您将要查看底层的 Fluent 查询构建器系统。就目前而言,您的查询是独立的。也有可能这个特定的人可能需要保持独立。
为了以您想要的方式连接到 Fluent,您需要传入查询(这应该会自动解析),添加到其中,然后 return 查询。关于您当前的功能,这可能需要与您所拥有的完全不同的方法(尽管您所拥有的是您希望最终得到的查询的良好模型)。
查看 the docs about query scopes, which may be addressing how you're trying to integrate it. Also, have a look at the code itself, such as this one for the JoinClause function,了解如何构建代码。
基本元素是您需要获取的元素和 return 查询对象。这意味着它不能是静态方法(它需要对象实例),并且根据您采用的方法,您将 returning 传入 $query
对象(范围) 或 $this
(它们模型对象的实例本身)。
您需要找到一种方法将您的查询封装到您需要的部分中。它可能是这样的:
public function byDistance($distance, $unit) {
$lat = Auth::user()->getLoc()->latitude;
$lng = Auth::user()->getLoc()->longitude;
return $this->join(DB::select('SELECT users.id, users.country, places.name, places.state_code, places.latitude, places.longitude, (' . $circle_radius . ' * acos(cos(radians(' . $lat . ')) * cos(radians(latitude)) *
cos(radians(longitude) - radians(' . $lng . ')) +
sin(radians(' . $lat . ')) * sin(radians(latitude)))
AS distance'),
'users.id', 'distance.user_id = users.id')
->leftJoin('places', 'users.suburb = places.name')
->where('distance', '<', $distance)
->orderBy('distance');
}
请注意查询构建部分中缺少实际的 select
(尽管有嵌套的 select),并且缺少任何类型的实际提取。它所做的是添加到当前查询中,然后在最终调用 get
或其他获取函数时构建该查询。这为您提供了一个较大查询的离散片段,您可以在调用它时将其添加到其中。
您也可以使用 sql 来完成。例如:
$filtr = "";
$filtr2 = "";
If (something)
$filtr =" and field = var";
If (somethingelse)
$filtr2 = " and field2 = other_var";
// this can be in the elloquent query
$query = "select ....
from ....
Where 1=1
$filtr
$filtr2
";
编辑
//assuming the country Id is passed to your controller
// first initialize the filter as empty string
$countryFilter = "";
// if the country is not null or empty replace the filter
if ($country != null && $country != "")
$countryFilter = "and country = $countryFilter";
$nearbyusers = DB::select(
'SELECT * FROM
(SELECT users.id, users.country, places.name, places.state_code, places.latitude, places.longitude, (' . $circle_radius . ' * acos(cos(radians(' . $lat . ')) * cos(radians(latitude)) *
cos(radians(longitude) - radians(' . $lng . ')) +
sin(radians(' . $lat . ')) * sin(radians(latitude))))
AS distance
FROM users
LEFT JOIN places ON users.suburb=places.name) AS distances
WHERE distance < ' . $max_distance . '
-- if no country was selected then it will just be an empty line
$countryFilter
ORDER BY distance;
');
嗯,还是老样子,自己解决了。问题很简单。您所要做的就是查找与结果匹配的用户对象并将它们推入数组。然后return那个数组,你就可以使用函数了!所以如果你想从原始查询中获取可传递的对象,这就是你要做的。再次感谢你们提供有用的答案。这个问题真的很简单。最后我摆弄它来工作,而不是从互联网上得到任何答案。
//spatial queries
$circle_radius = 6371;
// $circle_radius = 3959;
$max_distance = request('distance');
$lat = Auth::user()->getLoc()->latitude;
$lng = Auth::user()->getLoc()->longitude;
//get all nearby places
$nearbyusers = DB::select(
'SELECT * FROM
(SELECT users.id, users.country, places.name, places.state_code, places.latitude, places.longitude, (' . $circle_radius . ' * acos(cos(radians(' . $lat . ')) * cos(radians(latitude)) *
cos(radians(longitude) - radians(' . $lng . ')) +
sin(radians(' . $lat . ')) * sin(radians(latitude))))
AS distance
FROM users
LEFT JOIN places ON users.suburb=places.name) AS distances
WHERE distance < ' . $max_distance . '
ORDER BY distance;
');
$users = [];
foreach($nearbyusers as $user)
{
array_push($users, User::where('id', $user->id)->first());
}
//$nearbyusers = (object)$nearbyusers;
return Response::json( array(
'searchsuccess' => (String) view('members.yessearch', compact('users'))
) );