在没有冗余的情况下过滤数据时使用 eloquent

Using eloquent when filtering data without redundancy

我正在尝试通过 Eloquent 过滤数据,其方法仅响应 AJAX 请求,然后 returns 视图连同过滤后的数据。但是我有一个问题:

首先,让我们看一下我的代码:

public function AJAX_get_reports(Request $request)
{
    if($request->ajax())
    {
        $message = $request->get('message');
        $severity = $request->get('severity');

        if(strlen($message) > 0 && strlen($severity) > 0 )
        {
            $data = ServerReport::where('severity', '=', $severity)->where('message', '=', $message)->get();
        } elseif (strlen($message) > 0) {
            $data = ServerReport::where('message', '=', $message)->get();
        } elseif (strlen($severity) > 0) {
            $data = ServerReport::where('severity', '=', $severity)->get();
        } else {
            $data = ServerReport::all();
        }
        return Response::json(View::make('dashboard.reports.index', compact('data'))->render());

    }
}

这是我能够做到的唯一方法,它有效,但我觉得这不是最好的方法,特别是如果你有更多的字段要过滤,代码将在验证中占据很大的比例, 有没有最好的方法?

例如,在进行验证时构建查询,然后在最后运行它?

if(strlen($message) > 0)
{
    // add WHERE to query
}
if(strlen($severity) > 0)
{
    // add WHERE to query
}

// Execute query and get the results

考虑到您在原始代码中生成的内容对我来说看起来完全有效,我不确定是否一定有最佳方法,但肯定有选择。例如,如果您有经常使用的 WHERE 子句,则可以使用作用域来集中构建旨在实现特定结果的条件,并在必要时堆叠它们。这使您将来可以灵活地更改代码中的一个位置,并在必须修改您的条件的情况下影响使用更新范围的所有其他位置。但这可能与更大的代码可维护性问题有关,而不是我认为您在此特定实例中可能正在寻找的问题。

就我个人而言,我已经多次使用了您的假设方法。当我有一个可过滤的资源的 API 端点并且过滤器可以是可变的时,它对我来说非常有用。例如,按名字、姓氏、and/or 电子邮件的任意组合搜索用户。

这对我来说是这样的:

public function getIndex(Request $request, Response $response)
{
    //Start with a copy of the model
    //I prefer to instantiate the class from the container,
    //instead of having it auto-injected using the method signature
    //just personal preference
    $users = app('App\User');

    //Filter by first name
    if ($request->has('first_name')) {
        $users->where('first_name', $request->input('first_name'));
    }

    //Filter by last name
    if ($request->has('last_name')) {
        $users->where('last_name', $request->input('last_name'));
    }

    //Filter by email
    if ($request->has('email')) {
        $users->where('email', $request->input('email'));
    }

    //If no conditions were set, get() *should* function like all()
    $data = $users->get();

    //Do what you need with the data from here on out
    //Typically I paginate the results for something like this
}

出于几个原因,我认为这是一个很好的约定。首先,我发现代码具有很高的可读性,因为每个块都倾向于很好地自我记录(if request 电子邮件 ...)。其次,我可以轻松地删除任何需要在未来快速轻松地删除的块,而无需展开任何内容。

此方法的一个重要警告是每个过滤器都独立于其他过滤器 - 选择 0 个或多个过滤器的任意组合。如果您发现自己处于可以按组组合进行过滤的情况,事情就会变得有点棘手。即使在那里,您通常也可以将组合分成各自的块并实现大致相同的结果。

再一次,我认为你从问题的第一部分得到的是完全有效的,但建议将问题第二部分的代码作为更清晰、更易于维护的选项。

在我看来,您的代码可以像这样简化:

public function AJAX_get_reports(Request $request) {
    if($request->ajax()) {
        $message = $request->get('message');
        $severity = $request->get('severity');
        $report = ServerReport::select('*'); //Initiate the variable for query container, change * to the columns that needs to be returned or just leave it

        if (strlen($message) > 0) {
            $report->where('message', '=', $message); //Add message filter
        }

        if (strlen($severity) > 0) {
            $report->where('severity', '=', $severity); //Add severity filter
        }

        //Add another filters if needed

        $data = $report->get(); //Get the data from either the filtered data or every single data without any filters

        return Response::json(View::make('dashboard.reports.index', compact('data'))->render());
    }
}

我在公司的一些项目中使用了这个方法,一切正常。试一试。