简体   繁体   English

动态查询laravel雄辩与whereHas

[英]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. 并且所有参数都是变量namelike %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. 我假设您的ContactUserAccount模型中的关系函数是用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: 特别是,此示例有两件事有趣:

  • The 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()的变量。
  • Using $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. 使用ANDOR混合将需要更复杂的系统。

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM