みやもとメモ

「Notion」「Google Apps Script」「ブログカスタマイズ」などについて書いていきます。

目次
目次

【Laravel】カレンダーを月曜始まりに対応(.envファイルで切替可能)

この記事をシェアする

今回はLaravelに関して書いていきます。

以前もLaravelに関する記事を書いています(以下リンク)。

miya-moto-memo.hatenablog.com

上記の記事で、簡易的なカレンダーを作成しました。

「日曜始まり」固定で実装してしまいましたが、「月曜始まり」にも対応したいなと。

GoogleカレンダーやNotionのカレンダービューでも「日曜/月曜始まり」の切り替えができるようで、自分が実装したカレンダーでも対応したいなと。

それでは本題へ。

実行環境

実行環境は、

  • PHP 8.2.12
  • Laravel Framework 11.10.0
  • nesbot/carbon 3.5.0

です。

完成図

まずは手っ取り早く、完成図を貼ります。

月曜始まり

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に関してはいくつか記事にしています。
気になる記事があればぜひ。

TOPへ戻る HOMEへ