【问题标题】:Conditionally building an Eloquent query有条件地构建一个 Eloquent 查询
【发布时间】:2016-03-11 11:45:11
【问题描述】:

背景

我使用 Laravel 的 Eloquent 作为我的 ORM。我正在创建一个 API 端点,它提供对具有多个属性(color、make、status)的Cars 的访问。

我的端点允许客户端通过这些属性的任何子集过滤返回值,如果它们不提供任何属性,那么我将返回所有内容。

问题

我想构建一个条件查询,它从“全部”开始,并根据指定的参数缩小范围。这是我写的:

public function getCars(Request $request)
{
    $results = Cars::all();

    if($request->has('color'))
         $results = $results->where('color', $request->input('color'));

    if($request->has('make'))
         $results = $results->where('make', $request->input('make'));

    if($request->has('status'))
         $results = $results->where('status', $request->input('status'));

    return $results->toJson();
}

如果我在没有参数的情况下调用它,API 会返回数据库中所有汽车的列表。 但是,如果我指定(例如)0 的状态,API 会返回一个空集,尽管事实上有些汽车的状态是0。

我是不是在错误地处理这个问题?我是否缺少一些基本的东西?

请注意,如果我写的是:

$results = Cars::where('status', 0);
return $results->get();

正确生成汽车列表

【问题讨论】:

  • 你确定 $request->input('status') 等于 0 并且是从前端接收的,而不是像字符串这样的不同格式吗?
  • 好问题——是的,为了这个问题,我编辑了输入验证。
  • 您会得到$results->get() 的结果,因为它实际上返回了一个集合,而您的$results->toJson() 实际上是一个eloquent builder instance。在责备客户之前,请先尝试dd($results) 确定。

标签: php laravel laravel-5 eloquent laravel-query-builder


【解决方案1】:

为简单起见,您可以试试这个。

$query = Cars::query(); // no query executed, just give us a builder

$query->where(array_only($request->all(), ['color', 'make', 'status'])); // where can take a key value array to use
// update: only taking the vars you need, never trust incoming data

return $query->get(); // will be converted to Json for you

这只会查询您需要的数据库。你的返回所有结果,然后在集合中过滤它们。

更新: 正如 Joseph 所说,$request->only() 和 array_only 之间有不同的功能。这里需要array_only的功能。

【讨论】:

  • 对于这个特定的例子,我认为这种方法比手动执行一堆has 检查更干净。您也可以将其内联到 return Cars::where($request->all())->get();
  • 是的,我只是为了让 $query builder 部分脱颖而出。为了表明你可以这样使用它。
  • 这个方法看起来更干净,但不知何故,我担心我们实际上可以得到数据库中的所有内容。
  • idk 你的意思是什么,但这是一个简单的例子。你不应该使用 $request->all() 传递给它。你应该只接受你需要的输入,这样就没有人可以传递会破坏查询的额外字段。
  • 不要使用$request->only。对于请求中不存在的键,它将返回 null,这绝对不是您想要的。请改用array_only($request->all(), [....])。
【解决方案2】:

你应该像这样改变你的函数:

public function getCars(Request $request)
{
    $results = Cars::query();

    if($request->has('color'))
         $results = $results->where('color', $request->input('color'));

    if($request->has('make'))
         $results = $results->where('make', $request->input('make'));

    if($request->has('status'))
         $results = $results->where('status', $request->input('status'));

    return $results->get()->toJson();
}

【讨论】:

  • 哦,完美!谢谢你。在相关说明中,是否有比我链接到的更好的文档资源?我没有看到任何提及 query() 的内容!
  • query() 来自model instance。最好阅读 api 和源代码以了解更多信息:)
猜你喜欢
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2016-12-29
  • 2017-01-07
  • 2019-11-12
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
相关资源
最近更新 更多