今回はLaravelに関して書いていきます。
以前もLaravelに関する記事を書いています(以下リンク)。
上記の記事で、簡易的なカレンダーを作成しました。
「日曜始まり」固定で実装してしまいましたが、「月曜始まり」にも対応したいなと。
GoogleカレンダーやNotionのカレンダービューでも「日曜/月曜始まり」の切り替えができるようで、自分が実装したカレンダーでも対応したいなと。
それでは本題へ。
完成図
まずは手っ取り早く、完成図を貼ります。
月曜始まり
CALENDAR_WEEK_BEGIN=monday
日曜始まり
CALENDAR_WEEK_BEGIN=sunday
土曜始まり
CALENDAR_WEEK_BEGIN=saturday
こんな感じです。
切り替えは.envファイルで行っています。
ついでに「土曜始まり」にも対応しました。
Googleカレンダーを確認したところ土曜始まりに対応していたので、ついでに。
プログラム
プログラムは以下の通りです。
新規:calendar.php
<?php use Carbon\Carbon; return [ 'week_begin' => env('CALENDAR_WEEK_BEGIN', 'sunday'), 'week_begin_define' => [ 'saturday' => [ 'start' => Carbon::SATURDAY, 'end' => Carbon::FRIDAY, 'label' => ['土','日','月','火','水','木','金'], ], 'sunday' => [ 'start' => Carbon::SUNDAY, 'end' => Carbon::SATURDAY, 'label' => ['日','月','火','水','木','金','土'], ], 'monday' => [ 'start' => Carbon::MONDAY, 'end' => Carbon::SUNDAY, 'label' => ['月','火','水','木','金','土','日'], ], ] ];
変更:CalendarController.php
<?php namespace App\Http\Controllers; use App\Consts\CalendarConst; use App\Http\Controllers\Controller; use Carbon\Carbon; use Carbon\CarbonPeriod; use Illuminate\Http\Request; class CalendarController extends Controller { public function __invoke(Request $request) { // 週初めの定義を取得 $weekBegin = config('calendar.week_begin'); $weekBeginDefine = config("calendar.week_begin_define.{$weekBegin}"); // 当月を取得 $year = $request->input('year') ?? Carbon::today()->format('Y'); $month = $request->input('month') ?? Carbon::today()->format('m'); $thisMonth = Carbon::Create($year, $month, 01, 00, 00, 00); // 前月を取得 $previousMonth = $thisMonth->copy()->subMonth(); // 翌月を取得 $nextMonth = $thisMonth->copy()->addMonth(); // 当月の期間を取得 $thisMonthPeriod = $this->getThisMonthPeriod($thisMonth); // 前月の期間を取得 $previousMonthPeriod = $this->getPreviousMonthPeriod($thisMonth, $previousMonth, $weekBeginDefine['start']); // 翌月の期間を取得 $nextMonthPeriod = $this->getNextMonthPeriod($thisMonth, $nextMonth, $weekBeginDefine['end']); return view('calendar') ->with('thisMonth', $thisMonth) ->with('previousMonth', $previousMonth) ->with('nextMonth', $nextMonth) ->with('weekdayList', $weekBeginDefine['label']) ->with('thisMonthPeriod', $thisMonthPeriod) ->with('previousMonthPeriod', $previousMonthPeriod) ->with('nextMonthPeriod', $nextMonthPeriod) ; } /** * 当月の期間を取得 */ private function getThisMonthPeriod($thisMonth) { // 月初を取得 $start = $thisMonth->copy()->startOfMonth(); // 月末を取得 $end = $thisMonth->copy()->endOfMonth(); // 月初~月末の期間を取得 return CarbonPeriod::create($start->toDateString(), $end->toDateString())->toArray(); } /** * 前月の期間を取得 */ private function getPreviousMonthPeriod($thisMonth, $previousMonth, $calendarWeekStart) { // 当月の月初が"週始まりの曜日"ならArrayは空で if ($thisMonth->copy()->startOfMonth()->dayOfWeek === $calendarWeekStart) { return []; } // 前月の月末から始めて、"週始まりの曜日"になるまで日付を減らしていく $start = $previousMonth->copy()->endOfMonth(); while ($start->dayOfWeek !== $calendarWeekStart) { $start->subDays(); } // 前月の月末を取得 $end = $previousMonth->copy()->endOfMonth(); // 期間を取得 return CarbonPeriod::create($start->toDateString(), $end->toDateString())->toArray(); } /** * 翌月の期間を取得 */ private function getNextMonthPeriod($thisMonth, $nextMonth, $calendarWeekEnd) { // 当月の月末が"週終わりの曜日"ならArrayは空で if ($thisMonth->copy()->endOfMonth()->dayOfWeek === $calendarWeekEnd) { return []; } // 翌月の月初を取得 $start = $nextMonth->copy()->startOfMonth(); // 翌月の月初から始めて、"週終わりの曜日"になるまで日付を増やしていく $end = $nextMonth->copy()->startOfMonth(); while ($end->dayOfWeek !== $calendarWeekEnd) { $end->addDays(); } // 期間を取得 return CarbonPeriod::create($start->toDateString(), $end->toDateString())->toArray(); } }
変更:calendar.blade.php
<!DOCTYPE html> <html lang="ja"> <head> <meta charset="UTF-8"> <meta name="viewport" content="width=device-width, initial-scale=1.0"> <title>カレンダー</title> <link rel="stylesheet" href="{{ asset('/css/calendar.css') }}" > </head> <body> <div class="container"> <div class="header"> <a href="{{ url()->current() . '?year=' . $previousMonth->format('Y') . '&month=' . $previousMonth->format('m') }}">前月</a> <div>{{ $thisMonth->format('Y年m月') }}</div> <a href="{{ url()->current() . '?year=' . $nextMonth->format('Y') . '&month=' . $nextMonth->format('m') }}">翌月</a> </div> <div class="grid"> {{-- 曜日 --}} @foreach($weekdayList as $value) <div class="weekday">{{ $value }}</div> @endforeach {{-- 前月の期間 --}} @foreach ($previousMonthPeriod as $value) <div class="day not-this-month">{{ $value->format('j') }}</div> @endforeach {{-- 当月の期間 --}} @foreach ($thisMonthPeriod as $value) <div class="day this-month">{{ $value->format('j') }}</div> @endforeach {{-- 翌月の期間 --}} @foreach ($nextMonthPeriod as $value) <div class="day not-this-month">{{ $value->format('j') }}</div> @endforeach </div> </div> </body> </html>
変更:.env
CALENDAR_WEEK_BEGIN=monday
プログラム説明
configディレクトリに新規で「calendar.php」を作成しています。
ここに「土」「日」「月」それぞれの定義を書いています。
定義 | 始まり | 終わり |
---|---|---|
saturday | 土曜 | 金曜 |
sunday | 日曜 | 土曜 |
monday | 月曜 | 日曜 |
そして画面上で表示する曜日順をArrayで定義しています。
.envファイルで「saturday」「sunday」「monday」のいずれかを指定します。
Controllerで指定した曜日の定義を取得するように対応しています。
これにより、.envファイルを変更するだけで表示が切り替わります。
「○曜始まり」「○曜終わり」という定義は、前月・翌月の期間を取得する際に使用します。
この辺りは「CalendarController.php」の”$weekBeginDefine”あたりの内容を辿って頂ければと思います。
Controller側の処理を詳しく書いた以下記事も参考になるかなと思います。
miya-moto-memo.hatenablog.com
おわりに
ということで、「【Laravel】カレンダーを月曜始まりに対応(.envファイルで切替可能)」に関してアレコレ書いてみました。
本来なら画面上で「○曜始まり」を選択できるようにして、選択した情報はデータベースに保持する方法が一般的な気がします。
その辺りに関しては後ほど対応しようかなと思います。
とりあえず今回は.envファイルでの対応でした。
この記事が参考になれば幸いです。
関連記事
Laravelに関してはいくつか記事にしています。
気になる記事があればぜひ。