【问题标题】:Laravel query different result between (identical?) two vs three argument 'where' clauseLaravel 查询(相同?)两个与三个参数“where”子句之间的不同结果
【发布时间】:2017-07-19 13:57:09
【问题描述】:

我在 laravel (5.2) 中的查询遇到了一个非常奇怪的问题 - 我有一个从某个外部源(API)创建的集合,我正在尝试运行一个“where”查询来提取具体记录。

最初,我试图提取在当月提交的所有条目(因此,在本月的第一天之后)

$entries is the starting collection (time entries on a project - see end of post)

$thisMonthStart = (new Carbon('first day of this month'))->toDateString();
  //value of this is 2017-02-01, and the issue is not resolved if I remove toDateString()

$entriesThisMonth = $entries->where('spent-at', '>', $thisMonthStart); 
  //returns an empty collection, but should have 15 results

现在真正奇怪的部分是,我试图让 $entries 'spent-at' 等于每月的第一天 - 应该有一个条目。如果我明确指定比较运算符,我会得到我的预期结果:

$entriesThisMonth = $entries->where('spent-at', $thisMonthStart);
  //one $entries returned, see end of post

但是,如果我指定 = 运算符

$entriesThisMonth = $entries->where('spent-at', '=', $thisMonthStart);
  //empty collection returned

所以我现在很困惑 - 大概是我的原始集合中有问题,但为什么指定与不指定运算符有什么区别?我会认为这两个查询会给出相同的结果?

(显然,在尝试进行 比较时,无法指定运算符并不是很有帮助,但我主要只是对这两种语法之间的实际区别感兴趣,以及为什么它们给出不同的结果?)

我在任何地方都找不到关于这两个版本的查询如何工作的任何信息,所以如果预计它们会给出不同的结果 - 我认为它们应该是相同的,但也许有更深入了解的人可以解释一下这是什么原因造成的?

感谢任何可以解开谜团的人!


$entries 集合的示例以防万一(仅一条记录): (注意肯定有当月的记录,我知道这个例子太老了)

Collection {#952 ▼
  #items: array:367 [▼
175412141 => DayEntry {#958 ▼
  #_root: "request"
  #_convert: true
  #_values: array:16 [ …16]
  +"id": "175412141"
  +"notes": ""
  +"spent-at": "2013-10-03"
  +"hours": "0.75"
  +"user-id": "595841"
  +"project-id": "4287629"
  +"task-id": "2448666"
  +"created-at": "2013-10-03T18:07:54Z"
  +"updated-at": "2013-11-01T12:50:51Z"
  +"adjustment-record": "false"
  +"timer-started-at": ""
  +"is-closed": "false"
  +"is-billed": "true"
  +"started-at": "10:45"
  +"ended-at": "11:30"
  +"invoice-id": "3633772"
}

这就是 where 查询返回的内容没有运算符:

Collection {#954 ▼
  #items: array:1 [▼
568944822 => DayEntry {#1310 ▼
  #_root: "request"
  #_convert: true
  #_values: array:15 [▶]
  +"id": "568944822"
  +"notes": "Tweaking formatting on job ads and re shuffling ad order"
  +"spent-at": "2017-02-01"
  +"hours": "0.25"
  +"user-id": "595841"
  +"project-id": "4287629"
  +"task-id": "2448666"
  +"created-at": "2017-02-01T14:45:00Z"
  +"updated-at": "2017-02-01T14:45:00Z"
  +"adjustment-record": "false"
  +"timer-started-at": ""
  +"is-closed": "false"
  +"is-billed": "false"
  +"started-at": "14:30"
  +"ended-at": "14:45"
}
]
}

【问题讨论】:

    标签: laravel where-clause laravel-query-builder


    【解决方案1】:

    要解决您的问题...“返回一个空集合,但应该有 15 个结果”。如果集合已经存在,则需要filter 结果。像这样:

    $thisMonthStart = new Carbon('first day of this month');
    
    $entriesThisMonth = $entries->filter(function ($entry) use ($thisMonthStart) {
        return $entry['spent-at'] >= $thisMonthStart;
    });
    

    【讨论】:

    • Illuminate/Support/Collection 类型对象的 get 方法只是通过键从集合中检索一个元素,并且需要返回项的键作为参数传递才能工作。上面那个例子是行不通的
    • 刚刚注意到,如果$entries 集合已经存在,那么您是对的。他需要filter 结果。
    • 正如 Keir 正确猜到的那样,不幸的是,它不是一个雄辩的集合,所以 get() 不起作用 - 但 filter 选项确实有效,所以感谢您(以及上面的 Kier)!我将接受 Kier 的回答,因为他们更深入地了解不同 where 查询之间的区别,但也谢谢你! :)
    • 当然可以。 +1 我,我将不胜感激,特别是因为 Keir 推出了我的 filter 想法哈哈;p
    • 站在巨人的肩膀上.. :p 删除了我的 -1,因为你的答案现在也是正确的
    【解决方案2】:

    illuminate\Support\Collection::where 方法与数据库集合不同,它不将运算符作为第二个参数。

    您正在使用的集合对象的where 方法签名是where(string $key, mixed $value, bool $strict = true)

    您使用运算符的第二个示例是在集合中查找与字符串 '=' 匹配的所有元素。

    要进一步阅读您正在使用的集合(不是雄辩的集合),请查看here

    要获得您期望的 15 个结果,请对集合使用 filter 方法。

    按照这些思路应该可以工作:

    $entriesThisMonth = $entries->filter (function ($e) use ($thisMonthStart) {
    
        return $e ['spent-at'] > $thisMonthStart;
    
    });
    

    【讨论】:

    • 感谢您的解决方案以及解释和链接 - 我没有意识到两者之间的 where 方法不同,所以我会好好阅读!我稍微修改了您的代码以使其正常工作,因为 laravel 使用 $entries 的数组表示法会引发错误,并添加了 >=,但非常正确,谢谢! :) $entriesThisMonth = $entries->filter(function($i) use ($thisMonthStart){ return $i->{"spent-at"} >= $thisMonthStart; });
    猜你喜欢
    • 1970-01-01
    • 2019-10-22
    • 2014-09-29
    • 1970-01-01
    • 2013-12-30
    • 2018-12-22
    • 2022-12-17
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多