在Laravel中构建动态查询 - 如何进行多选项搜索

时间:2016-03-25 08:52:04

标签: php mysql laravel eloquent method-chaining

所以我试图设置一个搜索页面并且它有多个获取选项但是我很好奇如何正确设置它,我知道这远非正确,因为我在做if if语句里面设置一个变量,但我现在迷失了。

非常感谢任何帮助。

public function index()
{

    $queryUsername = Request::get('u');
    $queryPostcode = Request::get('p');
    $queryOrderbyPhotos = Request::get('o1');
    $queryOrderbyOnline = Request::get('o2');
    $queryOrderbyTypes = Request::get('o3');

    $users = User::rightJoin('user_profiles','users.id', '=', 'user_profiles.user_id')

    if ($queryUsername) 
    {
        ->where('users.username', '=', "$queryUsername")
    }
    if ($queryPostcode) {   
        ->where('user_profiles.postcode', '=', "$queryPostcode")
    }
    if ($queryOrderbyPhotos) {  
        ->whereNotNull('user_profile.avatar')
    }
    if ($queryOrderbyOnline) {  
        ->orderBy('users.last_online', 'DESC')
    }
    if ($queryOrderbyType) {    
        ->orderBy('users.type', 'DESC')
    }
    ->get();

    return view('view', compact('users'));
}

3 个答案:

答案 0 :(得分:3)

这就是我解决问题的方法。我将创建一个包含查询构建器的变量,然后在其上调用所有其他查询方法。

使用Eloquent并且实际上允许任何允许Method Chaining的类,您可以执行此操作:

$query = User::select(...)->join(..);
$query->where(...);
$query->get(...);

因此,在您的情况下,我将尝试以这种方式实现您想要的目标:

   public function index()
    {
        $input = Request::all();

        $query = User::rightJoin('user_profiles', 'users.id', '=', 'user_profiles.user_id');

        if (isset($input['u']) && $input['u'])
            $query->where('users.username', '=', $input['u']);

        if (isset($input['p'])  && $input['p'])
            $query->where('user_profiles.postcode', '=', $input ['p']);

        if (isset($input['o1']) && $input['o1'])
            $query->whereNotNull('user_profile.avatar');

        if (isset($input['o2']) && $input['o2'])
            $query->orderBy('users.last_online', 'DESC');

        if (isset($input ['o3']) && $input['o3'])
            $query->orderBy('users.type', 'DESC');

        $users = $query->get();

        return view('view', compact('users'));
    }

当然,对每个输入参数进行额外的有效输入检查是个好主意。但这可以通过多种方式实现。您可以详细了解Laravel Controller Validation Laravel Form Request Validation

顺便提一下,我建议将所有这些代码移到你的模型或单独的类中,因为我更喜欢保持控制器的纤薄。

答案 1 :(得分:2)

多选项搜索

这是可以被任何模型使用的特征

此功能会将重复的代码删除到您的项目中

public function scopeSearch($query, $keyword, $columns = [], $relativeTables = [])
{
    if (empty($columns)) {
        $columns = array_except(
            Schema::getColumnListing($this->table), $this->guarded
        );
    }   

    $query->where(function ($query) use ($keyword, $columns) {
        foreach ($columns as $key => $column) {
            $clause = $key == 0 ? 'where' : 'orWhere';
            $query->$clause($column, "LIKE", "%$keyword%");

            if (!empty($relativeTables)) {
                $this->filterByRelationship($query, $keyword, $relativeTables);
            }
        }
    });

    return $query;
}

也过滤到关系中

private function filterByRelationship($query, $keyword, $relativeTables)
{
    foreach ($relativeTables as $relationship => $relativeColumns) {
        $query->orWhereHas($relationship, function($relationQuery) use ($keyword, $relativeColumns) {
            foreach ($relativeColumns as $key => $column) {
                $clause = $key == 0 ? 'where' : 'orWhere';
                $relationQuery->$clause($column, "LIKE", "%$keyword%");
            }
        });
    }

    return $query;
}

答案 2 :(得分:1)

您可以尝试:

$users_query = new User;
$users_query->rightJoin(....);

if ($queryUsername)
{
    $users_query->where('users.username', '=', "$queryUsername")
}
// Your other conditions .....
....

$users = $users_query->get();