##はじめに
PHPでLaravelのCollectionクラスを利用しているときに、私が以前ハマった問題について共有します。
##動作環境
PHP 7.2
laravel/framework 6.0
##やりたいこと
日付のカラムを持つデータに対して、○日~△日の間という条件で絞り込みをしたい。
##問題のあった書き方
$between_days = getBetweenDays('2020-12-21', '2020-12-23');
foreach ($between_days as $date) {
var_dump($date->format('Y-m-d'));
}
public function getBetweenDays($start_date, $end_date) {
$date_list = collect([
['date' => new Carbon('2020-12-20')],
['date' => new Carbon('2020-12-21')],
['date' => new Carbon('2020-12-22')],
['date' => new Carbon('2020-12-23')],
['date' => new Carbon('2020-12-24')],
]);
return $date_list->whereBetween('date', [$start_date, $end_date])
->pluck('date')
->all();
}
// 結果
// string(10) "2020-12-21"
// string(10) "2020-12-22"
Carbon型にキャストされた日付情報に対して、String型で日付の情報を渡して絞り込みを行っています。
Laravelはかしこいので、こんなゆるい書き方でもエラーを吐かずに処理してくれます。
ですが、出力結果を見てみると、start_date側は境界の日付を含めて取得できていますが、end_date側は境界の日付を取得できていません。
単純なint型で絞り込みを行ったときは境界値を含めた絞り込みになるので、この挙動には問題があることが分かります。
##修正した書き方
$between_days = getBetweenDays(new Carbon('2020-12-21'), new Carbon('2020-12-23'));
foreach ($between_days as $date) {
var_dump($date->format('Y-m-d'));
}
public function getBetweenDays($start_date, $end_date) {
$date_list = collect([
['date' => new Carbon('2020-12-20')],
['date' => new Carbon('2020-12-21')],
['date' => new Carbon('2020-12-22')],
['date' => new Carbon('2020-12-23')],
['date' => new Carbon('2020-12-24')],
]);
return $date_list->whereBetween('date', [$start_date, $end_date])
->pluck('date')
->all();
}
// 結果
// string(10) "2020-12-21"
// string(10) "2020-12-22"
// string(10) "2020-12-23"
先程はString型で渡していた絞り込み条件を、予めCarbon型にキャストして絞り込みをしました。
出力結果を見てみると、start_dateもend_dateも境界値を含めて取得できています。
##さいごに
Collectionクラスに日付を自動で解釈させると、予期しない挙動をするかもしれない。という内容です。
Laravelの最新版では修正されているかもしれませんが、このような不具合にぶつからない為にも、ちゃんとデータの型を意識して扱おうと思った1件でした。