动态查询 laravel eloquent with whereHas
dynamic query laravel eloquent with whereHas
我想创建动态过滤器。
例如我想创建这个代码
$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();
并且所有参数都是可变的
name
,like
,%Jhone%
,family
,<>
,Doe
,.....
我想将变量传递给上面查询中创建的函数和函数。
我假设您的 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();
}
如果请求中没有 GET
参数,此函数将 return 所有联系人。如果存在 username
的参数,它只会 return 存在具有给定名称的用户的联系人。如果还存在 familyname
参数,它将提供与具有匹配用户名或姓氏的用户的联系方式。这同样适用于帐户、帐户名和城市。
这个例子有两点特别有趣:
when($value, $callback)
函数可用于构建非常动态的查询,仅在 $value
为真时才执行 $callback
。如果您使用 $request->get('something')
并且 something
不可用作参数,则该函数将 return null
并且不会执行回调。回调本身具有 function ($query, $value) { ... }
形式,其中 $value
是您作为第一个参数传递给 when()
的变量。
- 在查询构建器函数中使用
$request->has('something')
动态构建查询约束是 when()
的替代方法。我添加它只是为了演示目的 - 通常我会建议坚持一种风格。
如果你想扩展这个例子,你也可以构建高度动态的查询,其中不仅像 Doe
这样的姓氏的变量内容作为参数,而且像 [=33= 这样的比较器]、<>
或 like
。但是进一步扩展这个主题对于这个答案来说太多了,而且已经有关于这个主题的教程了。
编辑:这里是一个具有更详细输入的动态查询示例
预期输入(与您的请求略有不同,因为您的请求无法工作):
$filters = [
'user' => [
['name','like','%Jhone%'],
['family','<>','Doe'],
],
'account' => [
['account_name','=','test_account'],
['account_city','like','%test_city%'],
]
];
和函数:
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();
}
对于多个约束,这将始终使用 OR
而不是 AND
。混合使用 AND
和 OR
需要更复杂的系统。
我想创建动态过滤器。
例如我想创建这个代码
$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();
并且所有参数都是可变的
name
,like
,%Jhone%
,family
,<>
,Doe
,.....
我想将变量传递给上面查询中创建的函数和函数。
我假设您的 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();
}
如果请求中没有 GET
参数,此函数将 return 所有联系人。如果存在 username
的参数,它只会 return 存在具有给定名称的用户的联系人。如果还存在 familyname
参数,它将提供与具有匹配用户名或姓氏的用户的联系方式。这同样适用于帐户、帐户名和城市。
这个例子有两点特别有趣:
when($value, $callback)
函数可用于构建非常动态的查询,仅在$value
为真时才执行$callback
。如果您使用$request->get('something')
并且something
不可用作参数,则该函数将 returnnull
并且不会执行回调。回调本身具有function ($query, $value) { ... }
形式,其中$value
是您作为第一个参数传递给when()
的变量。- 在查询构建器函数中使用
$request->has('something')
动态构建查询约束是when()
的替代方法。我添加它只是为了演示目的 - 通常我会建议坚持一种风格。
如果你想扩展这个例子,你也可以构建高度动态的查询,其中不仅像 Doe
这样的姓氏的变量内容作为参数,而且像 [=33= 这样的比较器]、<>
或 like
。但是进一步扩展这个主题对于这个答案来说太多了,而且已经有关于这个主题的教程了。
编辑:这里是一个具有更详细输入的动态查询示例
预期输入(与您的请求略有不同,因为您的请求无法工作):
$filters = [
'user' => [
['name','like','%Jhone%'],
['family','<>','Doe'],
],
'account' => [
['account_name','=','test_account'],
['account_city','like','%test_city%'],
]
];
和函数:
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();
}
对于多个约束,这将始终使用 OR
而不是 AND
。混合使用 AND
和 OR
需要更复杂的系统。