如何在 Laravel 集合中的 where 子句中使用 Carbon 日期
How to use Carbon date in where clause in Laravel Collection
在过去的五个小时里,我一直在努力在 Laravel 5.2 项目的集合的 where 子句中使用 Carbon 日期……没有成功。
所以我首先从数据库中检索给定日期的预订约会集合:
$bookedRDVs = RDV::where('idAgenda', $idAgenda)
->whereDate('start', "=", $date)
->get();
然后我有一个营业时间 ([businessStart ; businessEnd]) 内的时间段列表(固定持续时间),我想将它们标记为空闲或不空闲。
$currentTime = $businessStart->copy(); // $businessStart is a Carbon date
while($currentTime < $businessEnd){
echo 'start is an object of class ' . get_class($bookedRDVs->first()->start); // start is an object of class Carbon\Carbon
echo 'currentTime is an object of class ' . get_class($currentTime); // currentTime is an object of class Carbon\Carbon
if($bookedRDVs->contains('start', $currentTime) ) {
$rdv = $bookedRDVs->where('start', $currentTime)->first();
var_dump($rdv); // prints NULL => why ?
} //end if
} // end while
为什么 $bookedRDVs->contains('start', $currentTime)
说 true ,但 $bookedRDVs->where('start', $currentTime)
说 null ? 'start' 是 Carbon 对象,$currentTime 也是 Carbon。
写这个问题的时候我的脑子里终于想到了whereLoose
而不是where
。实际上whereLoose
的结果不再是null了(所以这可能是解决方案,或者我的设计中存在我看不到的问题)。为什么对于相同的对象 class 和相同的值,where 子句未得到验证?
提前感谢您指出我在这里缺少的内容!
外卖(根据 Jeremy 的回答)
对于 5.3 之前的 Laravel,Collection 中的 where 子句进行严格比较(而 contains 进行松散比较)。这意味着只有当比较的 "things" 是彼此的克隆时,结果才为真。为了说服自己,我从我的代码中求助于这个例子:
$rdv = $bookedRDVs->whereLoose('start', $currentTime)->first();
echo '</br>' . 'start ';
var_dump($rdv->start); // prints object(Carbon\Carbon)#377 (3) { ["date"]=> string(26) "2016-09-13 09:20:00.000000" ["timezone_type"]=> int(3) ["timezone"]=> string(3) "UTC" }
echo '</br>' . 'currentTime ';
var_dump($currentTime); // prints object(Carbon\Carbon)#278 (3) { ["date"]=> string(26) "2016-09-13 09:20:00.000000" ["timezone_type"]=> int(3) ["timezone"]=> string(3) "UTC" }
echo '</br>' . ' start clone ';
var_dump(clone $rdv->start); // prints object(Carbon\Carbon)#377 (3) { ["date"]=> string(26) "2016-09-13 09:20:00.000000" ["timezone_type"]=> int(3) ["timezone"]=> string(3) "UTC" }
所以 $rdv->start
和 $currentTime
之间的唯一区别是井号 (see here for details). When those numbers differs it means that the object are not from the same instance. If $rdv->start
is cloned then the objects are really identical! Fortunately this has been changed in 5.3 according to the official upgrade doc 后面的数字。
如您所知,whereLoose()
对您有用。原因是该方法从字面上调用了 where()
方法,并且只是将 false
作为第三个参数传递给 严格类型检查 .
根据 documentation:
使用非严格比较(使用 contains()
和 whereLoose()
得到的结果),它将尝试兼顾类型。更具体地说,在这种情况下,如果对象具有 __toString()
方法(就像 Carbon 那样),它可以将其转换为字符串以尝试进行比较。
通过严格比较,它不会兼顾类型,因此会尝试将一个对象实例直接与另一个对象实例进行比较,尽管类型相同,但数据不同。
使用 PHP object comparison 时,使用 ===
的严格类型检查只有在“对象变量相同当且仅当它们引用相同 class 的相同实例”时才为真。
顺便问个好问题!
在过去的五个小时里,我一直在努力在 Laravel 5.2 项目的集合的 where 子句中使用 Carbon 日期……没有成功。
所以我首先从数据库中检索给定日期的预订约会集合:
$bookedRDVs = RDV::where('idAgenda', $idAgenda)
->whereDate('start', "=", $date)
->get();
然后我有一个营业时间 ([businessStart ; businessEnd]) 内的时间段列表(固定持续时间),我想将它们标记为空闲或不空闲。
$currentTime = $businessStart->copy(); // $businessStart is a Carbon date
while($currentTime < $businessEnd){
echo 'start is an object of class ' . get_class($bookedRDVs->first()->start); // start is an object of class Carbon\Carbon
echo 'currentTime is an object of class ' . get_class($currentTime); // currentTime is an object of class Carbon\Carbon
if($bookedRDVs->contains('start', $currentTime) ) {
$rdv = $bookedRDVs->where('start', $currentTime)->first();
var_dump($rdv); // prints NULL => why ?
} //end if
} // end while
为什么 $bookedRDVs->contains('start', $currentTime)
说 true ,但 $bookedRDVs->where('start', $currentTime)
说 null ? 'start' 是 Carbon 对象,$currentTime 也是 Carbon。
写这个问题的时候我的脑子里终于想到了whereLoose
而不是where
。实际上whereLoose
的结果不再是null了(所以这可能是解决方案,或者我的设计中存在我看不到的问题)。为什么对于相同的对象 class 和相同的值,where 子句未得到验证?
提前感谢您指出我在这里缺少的内容!
外卖(根据 Jeremy 的回答)
对于 5.3 之前的 Laravel,Collection 中的 where 子句进行严格比较(而 contains 进行松散比较)。这意味着只有当比较的 "things" 是彼此的克隆时,结果才为真。为了说服自己,我从我的代码中求助于这个例子:
$rdv = $bookedRDVs->whereLoose('start', $currentTime)->first();
echo '</br>' . 'start ';
var_dump($rdv->start); // prints object(Carbon\Carbon)#377 (3) { ["date"]=> string(26) "2016-09-13 09:20:00.000000" ["timezone_type"]=> int(3) ["timezone"]=> string(3) "UTC" }
echo '</br>' . 'currentTime ';
var_dump($currentTime); // prints object(Carbon\Carbon)#278 (3) { ["date"]=> string(26) "2016-09-13 09:20:00.000000" ["timezone_type"]=> int(3) ["timezone"]=> string(3) "UTC" }
echo '</br>' . ' start clone ';
var_dump(clone $rdv->start); // prints object(Carbon\Carbon)#377 (3) { ["date"]=> string(26) "2016-09-13 09:20:00.000000" ["timezone_type"]=> int(3) ["timezone"]=> string(3) "UTC" }
所以 $rdv->start
和 $currentTime
之间的唯一区别是井号 (see here for details). When those numbers differs it means that the object are not from the same instance. If $rdv->start
is cloned then the objects are really identical! Fortunately this has been changed in 5.3 according to the official upgrade doc 后面的数字。
如您所知,whereLoose()
对您有用。原因是该方法从字面上调用了 where()
方法,并且只是将 false
作为第三个参数传递给 严格类型检查 .
根据 documentation:
使用非严格比较(使用 contains()
和 whereLoose()
得到的结果),它将尝试兼顾类型。更具体地说,在这种情况下,如果对象具有 __toString()
方法(就像 Carbon 那样),它可以将其转换为字符串以尝试进行比较。
通过严格比较,它不会兼顾类型,因此会尝试将一个对象实例直接与另一个对象实例进行比较,尽管类型相同,但数据不同。
使用 PHP object comparison 时,使用 ===
的严格类型检查只有在“对象变量相同当且仅当它们引用相同 class 的相同实例”时才为真。
顺便问个好问题!