[英]dynamic query laravel eloquent with whereHas
I want to create dynamic filters. 我想创建动态过滤器。
for example I want to create this code 例如我想创建此代码
$Contact = Contact::whereHas('User', function ($query) use ($searchString) {
$query->where('name', 'like', '%Jhone%')->orwhere('family', '<>' . 'Doe');
})->whereHas('Account', function ($query) use ($searchString) {
$query->where('account_name', '=' , 'test_account' )->orwhere('account_city', 'like', '%test_city%');
})->get();
and all of parameters is variable name
, like
, %Jhone%
, family
, <>
, Doe
,..... and I want to pass variables to function and function create above query. 并且所有参数都是变量
name
, like
%Jhone%
, family
, <>
, Doe
,.....,我想将变量传递给函数,并在上面的查询中创建函数。
I assume that the relationship functions within your Contact
, User
and Account
models are written in camelCase
and not PascalCase
like your example shows. 我假设您的
Contact
, User
和Account
模型中的关系函数是用camelCase
编写的,而不是如示例所示的PascalCase
编写的。
public function getContacts(Request $request)
{
return Contact::when($request->get('username'), function ($query, $val) use ($request) {
$query->whereHas('user', function ($q) use ($val, $request) {
$q->where('name', 'like', '%'.$val.'%');
if ($request->has('familyname')) {
$q->orWhere('family', '<>', $request->get('familyname'));
}
});
})
->when($request->get('accountname'), function ($query, $val) use ($request) {
$query->whereHas('account', function ($q) use ($val, $request) {
$q->where('account_name', $val);
if ($request->has('city')) {
$q->orWhere('account_city', 'like', '%'.$request->get('city').'%');
}
});
})
->get();
}
This function will return all contacts when no GET
parameters are given on the request. 当请求中未提供
GET
参数时,此函数将返回所有联系人。 If a parameter for username
is present, it will only return contacts where a user with the given name exists for. 如果存在用于
username
的参数,它将仅返回具有给定名称的用户所在的联系人。 If furthermore a familyname
parameter is present, it will give contacts with a user that has a matching username or a familyname different from the one given. 如果还存在一个
familyname
参数,它将与用户名或姓氏匹配的用户进行联系。 The very same applies to the account, accountname and city. 帐户,帐户名和城市也是如此。
In particular, there are two things interesting about this example: 特别是,此示例有两件事有趣:
when($value, $callback)
function can be used to build very dynamic queries which only execute the $callback
when $value
is true. when($value, $callback)
函数可用于构建非常动态的查询,仅在$value
为true时才执行$callback
。 If you use $request->get('something')
and something
is not available as parameter, the function will return null
and the callback is not executed. $request->get('something')
且something
不可用作为参数,则该函数将返回null
且不执行回调。 The callback itself has the form function ($query, $value) { ... }
, where $value
is the variable you passed to when()
as first parameter. function ($query, $value) { ... }
,其中$value
是您作为第一个参数传递给when()
的变量。 $request->has('something')
inside the query builder functions to dynamically build constraints on the query is an alternative to when()
. $request->has('something')
在查询上动态建立约束是when()
的替代方法。 I only added it for the purpose of demonstration - in general I'd recomment sticking to one style. If you would extend on the example, you could also build highly dynamic queries where not only the variable content like Doe
for the family name is given as parameters, but also the comparator like =
, <>
or like
. 如果继续扩展该示例,则还可以构建高度动态的查询,其中不仅将诸如姓氏的
Doe
之类的变量内容作为参数,而且还提供=
, <>
或like
的比较器。 But extending further on this topic is too much for this answer and there are already tutorials about this topic available anyway. 但是,对于这个答案,进一步扩展该主题实在太多了,无论如何,已经有关于此主题的教程。
Edit: here an example for a dynamic query with more detailed input 编辑:这是具有更详细输入的动态查询的示例
Expected input (slightly different than your request because yours cannot work): 预期的输入(与您的请求略有不同,因为您的请求无法正常工作):
$filters = [
'user' => [
['name','like','%Jhone%'],
['family','<>','Doe'],
],
'account' => [
['account_name','=','test_account'],
['account_city','like','%test_city%'],
]
];
And the function: 和功能:
public function getContacts(Request $request, array $filters)
{
$query = Contact::query();
foreach ($filters as $key => $constraints) {
$query->whereHas($key, function ($q) use ($constraints) {
if (count($constraints) > 0) {
$q->where($constraints[0][0], $constraints[0][1], $constraints[0][2]);
}
for ($i = 1; $i < count($constraints); $i++) {
$q->orWhere($constraints[$i][0], $constraints[$i][1], $constraints[$i][2]);
}
});
}
return $query->get();
}
This will always use OR
for multiple constraints and not AND
. 这将始终对多个约束使用
OR
,而不对AND
进行约束。 Using AND
and OR
mixed would require a lot more sophisticated system. 使用
AND
和OR
混合将需要更复杂的系统。
声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.