カレンダーに関連するプロジェクトは、そのダイナミックなデータの性質上とても面白いです。また、店舗休日を表示するための月間カレンダーの生成とか、場所や部屋や物の予約のためのカレンダーのアプリとか実用的なものが多いです。私のお客さんのサイトでもチェックアウト画面でお客さんが届け日を指定するために月間のカレンダーが表示されます。カレンダーを題材にLaravelでどんなことが簡単にできるかをいくつかの投稿に分けて紹介します。

欲しいもの

簡単なところからということで、まず今月のカレンダーの表示から始めます。これを書いているのは2024年の10月なので、以下のような表示です。

Copilotでカレンダーの生成

私が生きている間にAIが開発者をヘルプできる時代になるとはまったく信じられなかったことですが、私も時代の流れに逆らえず、開発者のツールとしてマイクロソフトのCopilotを常時使用しています。Copilotは現時点ではChatGPT4を使用しており、VSCODEエディターの中からAIとの対話が可能です。

まず、以下の質問をCopilotに問います。

> 今月の月間のカレンダーを週と日にちの配列として生成するphp関数をCarbonのパッケージを使用して作成してください

以下のコードを作成してくれました。

以下は、Carbonパッケージを使用して今月の月間カレンダーを週と日にちの配列として生成するPHP関数です。
use Carbon\Carbon;

function getMonthlyCalendar()
{
    // 現在の月と年を取得
    $now = Carbon::now();
    $startOfMonth = $now->copy()->startOfMonth();
    $endOfMonth = $now->copy()->endOfMonth();

    // 月の最初の日の曜日を取得
    $startDayOfWeek = $startOfMonth->dayOfWeek;
    $totalDays = $endOfMonth->day;

    // カレンダーを作成する配列
    $calendar = [];
    $week = [];

    // 最初の週の空の日を追加
    for ($i = 0; $i < $startDayOfWeek; $i++) {
        $week[] = null; // 空のセル
    }

    // 日付を週に追加
    for ($day = 1; $day <= $totalDays; $day++) {
        $week[] = $day;

        // 7日ごとに新しい週を作成
        if (count($week) == 7) {
            $calendar[] = $week;
            $week = [];
        }
    }

    // 最後の週を追加
    if (count($week) > 0) {
        while (count($week) < 7) {
            $week[] = null; // 空のセル
        }
        $calendar[] = $week;
    }

    return $calendar;
}

説明のコメントつきでわかりやすいです。月間カレンダーはたいてい7×5あるいは7×4のグリッドですが、先月となる日や翌月となる日を非表示とする配慮が必要です。 この関数が返すデータを見せてもらいましょう。

> 今月は2024年10月として、上の関数が返す配列を見せてください
[
    [null, null, 1, 2, 3, 4, 5], // 1週目
    [6, 7, 8, 9, 10, 11, 12],    // 2週目
    [13, 14, 15, 16, 17, 18, 19], // 3週目
    [20, 21, 22, 23, 24, 25, 26], // 4週目
    [27, 28, 29, 30, 31, null, null] // 5週目
]

今月というのを説明しないと2023年の10月となってしまいますので注意を。
期待していた週と日の2次元の配列です。先月や翌月となっているところは、皆nullとなっています。

ここまでできるなら、後全部やってもらいましょう!

> それを利用したLaravelのコントローラとブレードを作成してください

以下はCopilotからの出力です。

以下は、提供されたコードを利用してLaravelのコントローラとブレードテンプレートを作成する方法です。

コントローラの作成
まず、CalendarControllerを完成させます。

namespace App\Http\Controllers;

use Illuminate\Http\Request;
use Carbon\Carbon;

class CalendarController extends Controller
{
    public function show()
    {
        $calendar = $this->getMonthlyCalendar();

        return view('calendar', compact('calendar'));
    }

    function getMonthlyCalendar()
    {
        // 現在の月と年を取得
        $now = Carbon::now();
        $startOfMonth = $now->copy()->startOfMonth();
        $endOfMonth = $now->copy()->endOfMonth();

        // 月の最初の日の曜日を取得
        $startDayOfWeek = $startOfMonth->dayOfWeek;
        $totalDays = $endOfMonth->day;

        // カレンダーを作成する配列
        $calendar = [];
        $week = [];

        // 最初の週の空の日を追加
        for ($i = 0; $i < $startDayOfWeek; $i++) {
            $week[] = null; // 空のセル
        }

        // 日付を週に追加
        for ($day = 1; $day <= $totalDays; $day++) {
            $week[] = $day;

            // 7日ごとに新しい週を作成
            if (count($week) == 7) {
                $calendar[] = $week;
                $week = [];
            }
        }

        // 最後の週を追加
        if (count($week) > 0) {
            // 残りの空の日を追加
            for ($i = count($week); $i < 7; $i++) {
                $week[] = null;
            }
            $calendar[] = $week;
        }

        return $calendar;
    }
}
ルートの定義
次に、ルートを定義します。
use App\Http\Controllers\CalendarController;

Route::get('/calendar', [CalendarController::class, 'show']);
ブレードテンプレートの作成
最後に、カレンダーを表示するためのブレードテンプレートを作成します。
<!DOCTYPE html>
<html>
<head>
    <title>Calendar</title>
    <img src="data:image/gif;base64,R0lGODlhAQABAIAAAAAAAP///yH5BAEAAAAALAAAAAABAAEAAAIBRAA7" data-wp-preserve="%3Cstyle%3E%0A%20%20%20%20%20%20%20%20table%20%7B%0A%20%20%20%20%20%20%20%20%20%20%20%20width%3A%20100%25%3B%0A%20%20%20%20%20%20%20%20%20%20%20%20border-collapse%3A%20collapse%3B%0A%20%20%20%20%20%20%20%20%7D%0A%20%20%20%20%20%20%20%20th%2C%20td%20%7B%0A%20%20%20%20%20%20%20%20%20%20%20%20border%3A%201px%20solid%20black%3B%0A%20%20%20%20%20%20%20%20%20%20%20%20text-align%3A%20center%3B%0A%20%20%20%20%20%20%20%20%20%20%20%20padding%3A%2010px%3B%0A%20%20%20%20%20%20%20%20%7D%0A%20%20%20%20%20%20%20%20th%20%7B%0A%20%20%20%20%20%20%20%20%20%20%20%20background-color%3A%20%23f2f2f2%3B%0A%20%20%20%20%20%20%20%20%7D%0A%20%20%20%20%3C%2Fstyle%3E" data-mce-resize="false" data-mce-placeholder="1" class="mce-object" width="20" height="20" alt="&lt;style&gt;" title="&lt;style&gt;" />
</head>
<body>
    <h1>Calendar for {{ \Carbon\Carbon::now()->format('F Y') }}</h1>
    <table>
        <tr>
            <th>Sunday</th>
            <th>Monday</th>
            <th>Tuesday</th>
            <th>Wednesday</th>
            <th>Thursday</th>
            <th>Friday</th>
            <th>Saturday</th>
        </tr>
        @foreach ($calendar as $week)
            <tr>
                @foreach ($week as $day)
                    <td>{{ $day ?? '' }}</td>
                @endforeach
            </tr>
        @endforeach
    </table>
</body>
</html>

曜日は英語ですが、あっという間にできてしまいました。

次の投稿では、Livewireを使ってカレンダーをリアクティブにします。

メルマガ購読の申し込みはこちらから。

By khino