日付ごとの配列を作りたい
日付ごとにデータを格納してViewに渡し、View側で日付ごとの表でデータを表示する、というパターンがよくある。そのために日付ごとの配列を生成して返すメソッドの配列パターンまとめ。Carbonを使うのでLaravelで使うことを想定。
よく書き忘れる
use Carbon\Carbon;
変数の初期化
$year = Carbon::now()->year;
$month = Carbon::now()->month;
1次元配列
1次元配列の場合
public function generateDaysOfMonthArray($year, $month) {
$start_day = Carbon::createFromDate($year, $month, 1)->startOfMonth();
$end_day = $start_day->copy()->endOfMonth();
$dateArray = [];
for ($current_day = $start_day; $current_day <= $end_day; $current_day->addDay()) {
$dateArray[$current_day->format('Y-m-d')] = $current_day;
}
return $dateArray;
}
$targetDate = '2023-11-15'; // 例として、取り出したい日付を指定
// $targetDateに対応する$current_dayを取り出す
$specificCurrentDay = $dateArray[$targetDate];
2次元配列
2次元配列の場合
public function generateDaysOfMonthArray($year, $month) {
$start_day = Carbon::createFromDate($year, $month, 1)->startOfMonth();
$end_day = $start_day->copy()->endOfMonth();
$dateArray = [];
for ($current_day = $start_day; $current_day <= $end_day; $current_day->addDay()) {
$dateArray[$current_day->format('Y-m-d')] = [
// $current_dayは文字列になるのでCarbonを入れとくと便利
'carbonDate' => $current_day,
// 'other_key' => $value,
];
}
return $dateArray;
}
$targetDate = '2023-11-15'; // 例として、取り出したい日付を指定
// $targetDateに対応する$current_dayを取り出す
$specificCurrentDay = $dateArray[$targetDate]['carbonDate'];
3次元配列
3次元配列の場合
public function generateDaysOfMonthArray($year, $month) {
$start_day = Carbon::createFromDate($year, $month, 1)->startOfMonth();
$end_day = $start_day->copy()->endOfMonth();
$dateArray = [];
for ($current_day = $start_day; $current_day <= $end_day; $current_day->addDay()) {
$dateArray[$current_day->format('Y-m-d')] = [
'carbon_date_time' => [
'carbonDate' => $current_day,
// 'key1' => $value1,
// 'key2' => $value2,
],
// 'other_key' => [
// 'key3' => $value3,
// 'key4' => $value4,
],
];
}
return $dateArray;
}
$targetDate = '2023-11-15'; // 例として、取り出したい日付を指定
// $targetDateに対応する$current_dayを取り出す
$specificCurrentDay = $dateArray[$targetDate]['carbon_date_time']['carbonDate'];
Controllerで使う
たとえば2次元配列をコントローラーで使う。
public function showDataPage(Request $request) {
// $yearと$monthは定義するなり$requestで受け取るなりする。
$dateArray = generateDaysOfMonthArray($year, $month);
foreach($dateArray as $date => $dataForDate) {
$dataArray['key1'] = [
// なんか定義する
];
}
return view('data_page', compact('dataArray'));
}
Viewで使う
<table>
<thead>
<tr>
<th> タイトル </th>
</tr>
</thead>
<tbody>
@foreach ($dateArray as $date => $dataForDate)
<tr>
<td>
<span>{{ $dataForDate['key1']['key2'] }}</span>
</td>
</tr>
@endforeach
</tbody>
</table>
とこんな感じで各データをループ処理して表示する。
休祝日を定義する
日付の配列生成時に休祝日のtrue:false
や、判定できる曜日を入れておくと便利。テキスト色の指定はtailwind css
の記述構文です。状況によってメソッドはstaticで定義するのもアリ。$this
使ってるので書き直さないとstaticにはできません。
春分の日
、秋分の日
、天皇誕生日
は日付が変わる可能性があるので、別に仕組みを実装する必要がある。なんかのAPI使うか、毎年定義をコードで追記するかDBテーブルを作って日付を登録するかして読み込む。
class Holiday extends Model { // DBに登録するならモデルとして実装
use HasFactory;
protected $fillable = ['date', 'column1', 'column2', 'column3'];
// その他リレーションとか必要な記述
// 'YYYY-MM-DD'の日付を渡すと休祝日を判定するメソッド
// 休祝日ならtrue、それ以外はfalseを返す
public function isHoliday($carbonDate)
{
$carbonDate = Carbon::parse($carbonDate);
// DBに休日が登録されている場合
$holidayRecords = Holiday::where('date', $carbonDate->format('Y-m-d'))->exists();
if ($holidayRecords) {
return true;
}
// 日曜日
if ($carbonDate->dayOfWeek == Carbon::SUNDAY) {
return true;
}
// 年によって変わる休日の設定
$yearUniequeHolidays = [
// Carbon::parse('2023-1-9')->toDateString(), // 2023_成人の日(1月第2月曜日)
Carbon::parse('2023-2-23')->toDateString(), // 2023_天皇誕生日(2018までは12-23)
Carbon::parse('2023-3-21')->toDateString(), // 2023_春分の日
// Carbon::parse('2023-7-17')->toDateString(), // 2023_海の日(7月第3月曜日)
// Carbon::parse('2023-9-18')->toDateString(), // 2023_敬老の日(9月第3月曜日)
Carbon::parse('2023-9-23')->toDateString(), // 2023_秋分の日
// Carbon::parse('2023-10-9')->toDateString(), // 2023_スポーツの日(10月第2月曜日)
];
// 年によって変わる休日(設定済み)の判定
if (in_array($carbonDate->toDateString(), $yearUniequeHolidays)) {
return true;
}
// 年によって変わるが定義が存在する休日の判定
if ($this->isSpecialMonday($carbonDate)) {
return true;
}
// 年によって変わらない休日の設定
$yearlyHolidays = [
Carbon::create($carbonDate->year, 1, 1)->format('m-d'), // 元日
Carbon::create($carbonDate->year, 1, 2)->format('m-d'), // 元日
Carbon::create($carbonDate->year, 1, 3)->format('m-d'), // 元日
Carbon::create($carbonDate->year, 2, 11)->format('m-d'), // 建国記念の日
Carbon::create($carbonDate->year, 4, 29)->format('m-d'), // 昭和の日(1989年から2006年までは"みどりの日")
Carbon::create($carbonDate->year, 5, 3)->format('m-d'), // 憲法記念日
Carbon::create($carbonDate->year, 5, 4)->format('m-d'), // みどりの日(2006年までは"国民の休日")
Carbon::create($carbonDate->year, 5, 5)->format('m-d'), // こどもの日
Carbon::create($carbonDate->year, 8, 11)->format('m-d'), // 山の日 (2016年に新設、特に山の意味はないらしい)
Carbon::create($carbonDate->year, 11, 3)->format('m-d'), // 文化の日
Carbon::create($carbonDate->year, 11, 23)->format('m-d'), // 勤労感謝の日
Carbon::create($carbonDate->year, 12, 30)->format('m-d'), // 年末休暇
Carbon::create($carbonDate->year, 12, 31)->format('m-d'), // 年末休暇
];
// 年によって変わらない休日の判定
if (in_array($carbonDate->format('m-d'), $yearlyHolidays)) {
return true;
}
// 振替休日の判定
if ($carbonDate->dayOfWeek == Carbon::MONDAY) {
$prevDay = $carbonDate->copy()->addDay(-1);
if (in_array($prevDay->format('m-d'), $yearlyHolidays)) {
return true;
}
}
// 上記の条件に当てはまらない場合は休日ではないと判定
return false;
}
private function isSpecialMonday($carbonDate)
{
// 指定された日が1月の第2月曜日、7月の第3月曜日、9月の第3月曜日、または10月の第2月曜日に該当するかどうかを判定
return (
// 1月の第2月曜日
($carbonDate->month == 1 && $carbonDate->dayOfWeek == Carbon::MONDAY && $carbonDate->weekOfMonth == 2) ||
// 7月の第3月曜日
($carbonDate->month == 7 && $carbonDate->dayOfWeek == Carbon::MONDAY && $carbonDate->weekOfMonth == 3) ||
// 9月の第3月曜日
($carbonDate->month == 9 && $carbonDate->dayOfWeek == Carbon::MONDAY && $carbonDate->weekOfMonth == 3) ||
// 10月の第2月曜日
($carbonDate->month == 10 && $carbonDate->dayOfWeek == Carbon::MONDAY && $carbonDate->weekOfMonth == 2)
) ?? false;
}
}
配列を生成する例。
private function generateDateArray($year, $month)
{
$startDate = Carbon::createFromDate($year, $month, 1)->startOfMonth();
$endDate = $startDate->copy()->endOfMonth();
$dateArray = [];
$daysOfWeekInJapanese = ['日', '月', '火', '水', '木', '金', '土'];
$myHoliday = new Holiday(); // isHolidayをstaticメソッドにする場合この行は不要
// 日付をキーとした多次元配列を構築
for ($currentDate = $startDate; $currentDate->lte($endDate); $currentDate->addDay()) {
$dayOfWeek = $currentDate->dayOfWeek; // 曜日を数値で取得
$holidayFlag = $myHoliday->isHoliday($currentDate); // 休祝日フラグ
$textColor = ''; // viewで使うテキストの文字色
if ($dayOfWeek == 0 || $holidayFlag == true) {
$textColor = 'text-red-400'; // 休日は赤で表示
} elseif ($dayOfWeek == 6) {
$textColor = 'text-cyan-400'; // 土曜日は青で表示
}
$dateArray[$currentDate->format('Y-m-d')] = [
'carbonDate' => Carbon::parse($currentDate),
'stringDate' => Carbon::parse($currentDate)->format('Y-m-d'),
'formattedDate' => Carbon::parse($currentDate)->format('Y-m-d (') . $daysOfWeekInJapanese[$dayOfWeek] . ')',
'holiday_flag' => $holidayFlag,
'dayOfWeek' => $dayOfWeek,
'textColor' => $textColor,
];
}
return $dateArray;
}
Viewでのテキスト色指定の例。
<span class="{{ $dataForDate['textColour'] }}">テキスト<span>