• 考え方
  • コントローラー
  • ビュー
  • ルート

laravelにてカレンダーを作成したのでメモがてら共有します。
phpの関数を使って作成していきます。
ツールを使った作成はしていないです。

使用する関数

array_fill(開始番号, 個数, 入れたい中身);

もし ym が無かったら ○○ を使うという意味
request('ym', date('Y-m'));

intを入れると整数になる。なしだと文字列になる
(int)date('w', $timestamp);

文字列で認識されている数字をコンピューターが使える数字に変える
strtotime("時間のずらし方", 基準の時間)
strtotime("文字の日時")

変数が空(null、0、空文字、false、空配列など)であるかを確認する
empty()

今回はこれらの知識を活用して下記の画像のようなものをつくります。
image.png

コントローラー

public function home()
    {
        //今月の年月を表示
        //もし ym が無かったら ○○ を使うという意味
        $ym = request('ym', date('Y-m'));
        // 今月の1日を取得
        $timestamp=strtotime($ym . '-01'); 
        // 今月1日の曜日を取得
        //intを入れると整数になる。なしだと文字列になる
        $youbi = (int)date('w', $timestamp);
        $startyoubi = (int)date('w', $timestamp);
        //該当月の月末日を取得
        $day_count = date('t', $timestamp);
        //カレンダー作成の準備
        $weeks = [];
        $week  = array_fill(0, $startyoubi, null); 
        // array_fill(開始番号, 個数, 入れたい中身);
        // 先月・今月・翌月
        $today = date('Y-m');
        //strtotime("時間のずらし方", 基準の時間)やstrtotime("文字の日時")として使う。文字列で認識されている数字をコンピューターが使える数字に変える
        $prev = date('Y-m', strtotime('-1 month', $timestamp));
        $next = date('Y-m', strtotime('+1 month', $timestamp));

        for($day = 1; $day <= $day_count; $day++,$youbi++){
            $week[] = $day; 
            if (($youbi % 7) == 6) {
                $weeks[] = $week;
                $week = [];
            }elseif(($youbi % 7) > 5){
                $weeks[] = $week;
                $week = [];
            }

        }
        // empty()は、変数が空(null、0、空文字、false、空配列など)であるかを確認する
        //残っている場合は配列に追加される
        if (!empty($week)) {
            $weeks[] = $week; // 最後の週
        }
        return view('home', compact('weeks','youbi','prev','next','today'));
    }

コントローラーでの考え方はこの↓の配列を作ることをゴールに考えるとわかりやすいです!
配列の考え方

$weeks = [
  [null, null, null, 1, 2, 3, 4],
  [5,6,7,8,9,10,11],
  [12,13,14,15,16,17,18],
  [19,20,21,22,23,24,25],
  [26,27,28,29,30,31]
];

この配列を作るための処理がこちら

for($day = 1; $day <= $day_count; $day++,$youbi++){
    $week[] = $day; 
    曜日は0~6(0→土曜 〜 6→日曜)で取得されるので6で1つにします
    if (($youbi % 7) == 6) {
        $weeks[] = $week;
        ↓これで一度リセット
        $week = [];
    }elseif(($youbi % 7) > 5){
        $weeks[] = $week;
        $week = [];
    }

}

↓個人的にはこのコードが一番大事

$week  = array_fill(0, $startyoubi, null); 
// array_fill(開始番号, 個数, 入れたい中身);

1日が土曜日からではない場合は、1日が始まる曜日までnullを入れる必要がある
nullをいれないとどの月でも土曜日が1日になってしまいおかしくなる。

続いてビュー

<table class="calendar">
  <thead>
    <tr>
      <th>日</th><th>月</th><th>火</th><th>水</th><th>木</th><th>金</th><th>土</th>
    </tr>
  </thead>
  <tbody>
  「?」→URLに「データをくっつけますよ」っていう合図。
    <a href="?ym={{ $prev }}">← 前月</a>
    <a href="?ym={{ $today }}">今月</a>
    <a href="?ym={{ $next }}">次月 →</a>
    @foreach ($weeks as $week)
    <tr>
        @foreach($week as $day)
            @if($day === null)
                <td></td>
            @else
                <td>{{$day}}</td>
            @endif
        @endforeach
    @endforeach
  </tbody>
</table>

1個1個解説します

<table class="calendar">
  <thead>
    <tr>
      <th>日</th><th>月</th><th>火</th><th>水</th><th>木</th><th>金</th><th>土</th>
    </tr>
  </thead>
  <tbody>
  <td></td>
  </tbody>
</table>

これはシンプルにhtmlです

   @foreach ($weeks as $week)
    <tr>
        @foreach($week as $day)
        @endforeach
    @endforeach

ここでは配列を一個ずつ呼び出しています
イメージはこんな感じ

$weeks = [
  [1],
  [2],
  [3],
  [4],
  [5]
];

2個目のforeachで[1]の中身

  [null, null, null, 1, 2, 3, 4],

なので配列の中に配列がある形になります。

 @foreach($week as $day)
    @if($day === null)
        <td></td>
    @else
        <td>{{$day}}</td>
    @endif
@endforeach

dayには日が入っているのですがnullの場合は空にして
入っている場合はdayで日を表示

必要ないと思うけどルート

Route::controller(CalendarController::class)->group(function () {
    Route::get('/', 'home')->name('home');
});

これで一通りカレンダーができます。
ここから投稿したりできるようにするためには追加で処理が必要になります。