8-1:カレンダーを実装する

2019/05/30

概要

コーポレートサイト上で予約受け付けをできるようにする機能を作っていきます。
この章では、予約機能の基準となるカレンダーを作成していきます。

フォルダ階層

完成イメージ

カレンダー

全体の手順

手順は以下のとおりです

  1. 日付操作ライブラリをインストール
  2. カレンダーの作成
  3. デザイン適用

日付操作ライブラリをインストール

カレンダーを作成していく上で、Carbonというライブラリをインストールして作っていきたいと思います。
CarbonとはPHPのDateTimeクラスをオーバーラップした日付操作ライブラリです。
PHPのwebフレームワークとして広く世界で利用されているLaravelにもデフォルトでインストールされていています。
うるう年の対応など、DateTimeクラスではややこしいものもCarbonは対応しているのでとても便利です。
インストールしていきます。
インストールにはcomposerを利用します。

composerのインストールチェック

composerを使ってrequireしたいのでcomposerコマンドが使えるか確認します。
console

$ composer -v

結果が下記のように返ってくればcomposerコマンドが使えるのでこのまま進みます。
console

   ______
  / ____/___  ____ ___  ____  ____  ________  _____
 / /   / __ \/ __ `__ \/ __ \/ __ \/ ___/ _ \/ ___/
/ /___/ /_/ / / / / / / /_/ / /_/ (__  )  __/ /
\____/\____/_/ /_/ /_/ .___/\____/____/\___/_/
                    /_/
Composer version 1.6.3 2018-01-31 16:28:17

Usage:
  command [options] [arguments]

Options:
  -h, --help                     Display this help message
  -q, --quiet                    Do not output any message
  -V, --version                  Display this application version
      --ansi                     Force ANSI output
      --no-ansi                  Disable ANSI output
  -n, --no-interaction           Do not ask any interactive question
      --profile                  Display timing and memory usage information
      --no-plugins               Whether to disable plugins.
  -d, --working-dir=WORKING-DIR  If specified, use the given directory as working directory.
  -v|vv|vvv, --verbose           Increase the verbosity of messages: 1 for normal output, 2 for more verbose output and 3 for debug

Available commands:
  about                Shows the short information about Composer.
  archive              Creates an archive of this composer package.
  browse               Opens the package's repository URL or homepage in your browser.
  check-platform-reqs  Check that platform requirements are satisfied.
  clear-cache          Clears composer's internal package cache.
  clearcache           Clears composer's internal package cache.
  config               Sets config options.
  create-project       Creates new project from a package into given directory.
  depends              Shows which packages cause the given package to be installed.
  diagnose             Diagnoses the system to identify common errors.
  dump-autoload        Dumps the autoloader.
  dumpautoload         Dumps the autoloader.
  exec                 Executes a vendored binary/script.
  global               Allows running commands in the global composer dir ($COMPOSER_HOME).
  help                 Displays help for a command
  home                 Opens the package's repository URL or homepage in your browser.
  info                 Shows information about packages.
  init                 Creates a basic composer.json file in current directory.
  install              Installs the project dependencies from the composer.lock file if present, or falls back on the composer.json.
  licenses             Shows information about licenses of dependencies.
  list                 Lists commands
  outdated             Shows a list of installed packages that have updates available, including their latest version.
  prohibits            Shows which packages prevent the given package from being installed.
  remove               Removes a package from the require or require-dev.
  require              Adds required packages to your composer.json and installs them.
  run-script           Runs the scripts defined in composer.json.
  search               Searches for packages.
  self-update          Updates composer.phar to the latest version.
  selfupdate           Updates composer.phar to the latest version.
  show                 Shows information about packages.
  status               Shows a list of locally modified packages.
  suggests             Shows package suggestions.
  update               Upgrades your dependencies to the latest version according to composer.json, and updates the composer.lock file.
  upgrade              Upgrades your dependencies to the latest version according to composer.json, and updates the composer.lock file.
  validate             Validates a composer.json and composer.lock.
  why                  Shows which packages cause the given package to be installed.
  why-not              Shows which packages prevent the given package from being installed.

結果が下記のようにnot foundで返ってきたらcomposerをインストールする必要があるのでローカル開発環境でhomebrewとcomposerをインストールするを参照してcomposerを使えるようにしてから次へ進みます。
console

-bash: composer: command not found

composerでCarbonの追加

console

$ cd corporate-site
$ composer require nesbot/carbon

インストールが始まり、最後にGenerating autoload filesと表示されコンソールが返ってきていればOKです。
console

Using version ^2.18 for nesbot/carbon
./composer.json has been updated
Loading composer repositories with package information
Updating dependencies (including require-dev)
Package operations: 4 installs, 0 updates, 0 removals
  - Installing symfony/polyfill-mbstring (v1.11.0): Loading from cache
  - Installing symfony/contracts (v1.1.0): Downloading (100%)         
  - Installing symfony/translation (v4.2.8): Downloading (100%)         
  - Installing nesbot/carbon (2.18.0): Downloading (100%)         
symfony/contracts suggests installing psr/cache (When using the Cache contracts)
symfony/contracts suggests installing psr/container (When using the Service contracts)
symfony/contracts suggests installing symfony/cache-contracts-implementation ()
symfony/contracts suggests installing symfony/event-dispatcher-implementation ()
symfony/contracts suggests installing symfony/http-client-contracts-implementation ()
symfony/contracts suggests installing symfony/service-contracts-implementation ()
symfony/translation suggests installing symfony/config ()
symfony/translation suggests installing symfony/yaml ()
symfony/translation suggests installing psr/log-implementation (To use logging capability in translator)
Writing lock file
Generating autoload files
$

一応、フォルダを確認してみましょう。
corporate-siteフォルダに/vendor/nesbot/carbonがあればOKです。

カレンダーの作成

カレンダーを作成していきます。
corporate-siteフォルダ内にcalendar.phpという名前のファイルを作成します。

Carbonの読み込み

まずはじめに、インストールしたCarbonが利用できるように読み込みをします。
calendar.php

<?php
    require 'vendor/autoload.php';
    use Carbon\Carbon;

今月のカレンダーを表示

とりあえず、今月のカレンダーを表示してみます。

今日を取得

完成形に辿り着く頃にはコードが長くなるので、renderCalendar()を叩いたらカレンダーが表示されるようにrendarCalendar()というfunctionを作成していきます。
とりあえず、$dtで今の時間を取得して、renderCalendar()に$dtを渡します。
createFromDate()はUTCの時間になっているので、日本の時刻に変換させます。
calendar.php

    <?php
        require 'vendor/autoload.php';
        use Carbon\Carbon;

+      $dt = Carbon::createFromDate();
+      renderCalendar($dt);
+      
+      function renderCalendar($dt)
+      {
+          $dt->timezone = 'Asia/Tokyo'; //日本時刻で表示
+          echo $dt;
+      }

この状態でブラウザを開くと、2019-05-30 11:47:47というような形式で日本の現在時刻が表示されるはずです。

次に、カレンダーを表示する上で、今月の最初の日(今日が5月30日だったら、5月1日。今日が6月3日だったら6月1日)を取得する必要があるので、今月の最初の日を取得する記述を追加します。
calendar.php

    <?php
        require 'vendor/autoload.php';
        use Carbon\Carbon;

        $dt = Carbon::createFromDate();
        renderCalendar($dt);

        function renderCalendar($dt)
        {
+         $dt->startOfMonth(); //今月の最初の日
            $dt->timezone = 'Asia/Tokyo'; //日本時刻で表示
            echo $dt;
        }

この状態でブラウザを開くと、2019-05-01 09:00:00というような形式で今月の最初の日が表示されているはずです。

曜日を取得

日付は取得できるようになりました。
次に、カレンダーのトップに必要なMonday〜Sundayまでの曜日の表示をtableのtheadに設定します。
曜日を配列に入れて、ループで回して表示しています。
calendar.php

    function renderCalendar($dt){
        $dt->startOfMonth();
        $dt->timezone = 'Asia/Tokyo';
-      echo $dt;    

+      //曜日の配列作成
+      $headings = ['Monday','Tuesday','Wednesday','Thursday','Friday','Saterday','Sunday'];
+   
+      $calendar = '<table class="table" border=1>';
+      $calendar .= '<thead >';
+      foreach($headings as $heading){
+          $calendar .= '<th class="header">'.$heading.'</th>';
+      }
+      $calendar .= '</thead>';
+      $calendar .= '</table>';
+   
+      echo $calendar;

    }

表示させてみます。

日付を表示

日付を表示するのは今月の日数の数だけループでまわす必要があるので、daysInMonthを使って今月の日数を取得します(例:1月なら31、2月なら28)。
取得できたら、1日〜日数分ループを回します。
一旦ただ表示させてみます。
calendar.php

    $calendar .= '</thead>';

+   $calendar .= '<tbody><tr>';
+
+
+   //今月は何日まであるか
+   $daysInMonth = $dt->daysInMonth;
+   
+   for ($i = 1; $i <= $daysInMonth; $i++) {
+       $calendar .= '<td class="day">'.$dt->day.'</td>';
+       $dt->addDay();
+   }
+
+   $calendar .= '</tr></tbody>';

    $calendar .= '</table>';

ブラウザで確認します。

日数分表示はできていますが、折返しもなく、1日が始まる位置も正しくありません。

カレンダーを作成するにあたって、必要なことは、

  1. 1日は何曜日から始まるかを認識する
  2. 月曜日が来たら改行する

ということです。

1日の曜日を取得

指定した日が何曜日かは、format('N')で取得できます。
format('N')の返り値は1〜7の数字です。
1=Monday,2=Tuesday,3=Wednesday....となっています。

先程、ただ表示したら、1日は最初のカラムのMondayから表示されました。
なので、1日がMonday以外の場合は表示場所を指定するように実装しなければいけません。
1日が月曜じゃない場合はcolspanでその分間を空けるように記述します。
calendar.php

    for ($i = 1; $i <= $daysInMonth; $i++) {
+        if($i==1){
+            if ($dt->format('N')!= 1) {
+                $calendar .= '<td colspan="'.($dt->format('N')-1).'"></td>'; //1日が月曜じゃない場合はcospanでその分あける
+            }
+        }
        $calendar .= '<td class="day">'.$dt->day.'</td>';
        $dt->addDay();
    }

確認してみます。
チェック方法は、冒頭の$dt = Carbon::createFromDate();に部分を$dt = Carbon::createFromDate(2019,05,01);のように(年,月,日)を指定してチェックしてみます。
1日が正しい曜日の位置から表示されていることを確認します。

$dtに2019年5月1日を指定した場合。

$dtに2019年2月25日を指定した場合。

確認できたら$dt = Carbon::createFromDate(2019,02,25);$dt = Carbon::createFromDate();に戻しておきます。
1日のスタート位置が正しい位置に動的に変更されるようになりました。
まだ、月曜日で改行はされていません。

月曜日で改行させる

月曜日が来たら改行させて、カレンダーらしく表示させるようにしていきます。
calendar.php

    for ($i = 1; $i <= $daysInMonth; $i++) {
        if($i==1){
            if ($dt->format('N')!= 1) {
                $calendar .= '<td colspan="'.($dt->format('N')-1).'"></td>'; //1日が月曜じゃない場合はcospanでその分あける
            }
        }

+       if($dt->format('N') == 1){
+           $calendar .= '</tr><tr>'; //月曜日だったら改行
+       }

        $calendar .= '<td class="day">'.$dt->day.'</td>';
        $dt->addDay();
    }

確認します。

カレンダーらしくなりました。

前月・来月のカレンダーを表示

月送りリンクを作って、前月・来月を動的に表示できるようにします。
1ヶ月前を表示するために、$dtをもとに、新しくオブジェクトを作成して、subMonth()を使って1ヶ月前の年・月を取得します。
calendar.php

    function renderCalendar($dt){
        $dt->startOfMonth();
        $dt->timezone = 'Asia/Tokyo';

+       //1ヶ月前
+       $sub = Carbon::createFromDate($dt->year,$dt->month,$dt->day);
+       $subMonth = $sub->subMonth();
+       $subY = $subMonth->year;
+       $subM = $subMonth->month;

1ヶ月後を表示するために、$dtをもとに、新しくオブジェクトを作成して、addMonth()を使って1ヶ月後の年・月を取得します。
calendar.php

    $dt->startOfMonth();
    $dt->timezone = 'Asia/Tokyo';

    //1ヶ月前
    $sub = Carbon::createFromDate($dt->year,$dt->month,$dt->day);
    $subMonth = $sub->subMonth();
    $subY = $subMonth->year;
    $subM = $subMonth->month;

+   //1ヶ月後
+   $add = Carbon::createFromDate($dt->year,$dt->month,$dt->day);
+   $addMonth = $add->addMonth();
+   $addY = $addMonth->year;
+   $addM = $addMonth->month; 

1ヶ月前・1ヶ月後のリンクを$titleという変数に入れて、表示をします。
calendar.php

    //1ヶ月後
    $add = Carbon::createFromDate($dt->year,$dt->month,$dt->day);
    $addMonth = $add->addMonth();
    $addY = $addMonth->year;
    $addM = $addMonth->month;    

+   //リンク
+   $title = '<caption><a href="./calendar.php?y='.$subY.'&&m='.$subM.'"><<前月 </a>';//前月のリンク
+   $title .= $dt->format('F Y');//月と年を表示
+   $title .= '<a href="./calendar.php?y='.$addY.'&&m='.$addM.'"> 来月>></a></caption>';//来月リンク  

    //曜日の配列作成
    $headings = ['Monday','Tuesday','Wednesday','Thursday','Friday','Saterday','Sunday'];

    $calendar = '<table class="table" border=1>';
    $calendar .= '<thead >';
    foreach($headings as $heading){
        $calendar .= '<th class="header">'.$heading.'</th>';
    }
    $calendar .= '</thead>';

    $calendar .= '<tbody><tr>';

    //今月は何日まであるか
    $daysInMonth = $dt->daysInMonth;

    for ($i = 1; $i <= $daysInMonth; $i++) {
        if($i==1){
            if ($dt->format('N')!= 1) {
                $calendar .= '<td colspan="'.($dt->format('N')-1).'"></td>'; //1日が月曜じゃない場合はcospanでその分あける
            }
        }

        if($dt->format('N') == 1){
            $calendar .= '</tr><tr>'; //月曜日だったら改行
        }

        $calendar .= '<td class="day">'.$dt->day.'</td>';
        $dt->addDay();
    }

    $calendar .= '</tr></tbody>';

    $calendar .= '</table>';

-   echo $calendar; 
+   echo $title.$calendar; 

取得した年・月をgetで受け取って、$dt作成に反映します。
$m$yどちらかでも空の場合は今日を設定します。
calendar.php

-   $dt = Carbon::createFromDate();
+   $m = isset($_GET['m'])? htmlspecialchars($_GET['m'], ENT_QUOTES, 'utf-8') : '';
+   $y = isset($_GET['y'])? htmlspecialchars($_GET['y'], ENT_QUOTES, 'utf-8') : '';
+   if($m!=''||$y!=''){
+       $dt = Carbon::createFromDate($y,$m,01);
+   }else{
+       $dt = Carbon::createFromDate();
+   }
    renderCalendar($dt);

表示中の月、前月・来月リンクが表示され、リンクをクリックすると前月・来月が表示されることを確認します。

今日リンクも追加

一応、今月のカレンダーにすぐ戻れるように今月のリンクも付けます。
calendar.php

        //1ヶ月後
        $add = Carbon::createFromDate($dt->year,$dt->month,$dt->day);
        $addMonth = $add->addMonth();
        $addY = $addMonth->year;
        $addM = $addMonth->month;

+       //今月
+       $today = Carbon::createFromDate();
+       $todayY = $today->year;
+       $todayM = $today->month;

+       //リンク
+       $title = '<caption><a href="./calendar.php?y='.$todayY.'&&m='.$todayM.'">今日 </a>';
+       $title .= '<a href="./calendar.php?y='.$subY.'&&m='.$subM.'"><<前月 </a>';//前月のリンク
-       $title = '<caption><a href="./calendar.php?y='.$subY.'&&m='.$subM.'"><<前月 </a>';//前月のリンク
        $title .= $dt->format('F Y');//月と年を表示
        $title .= '<a href="./calendar.php?y='.$addY.'&&m='.$addM.'"> 来月>></a></caption>';//来月リンク

確認します。
今日をクリックして、今月のカレンダーに戻ればOKです。

土日に色を付ける

土曜日はブルー、日曜日は赤の背景にしてみます。
format('N')で曜日を判断し、分岐文で色分けします。
インラインでスタイルを設定します。
土曜日はformat('N')で6という結果が返ってきます。6だった場合土曜日なので、tdの背景にstyle="background-color:#b0e0e6"を追加します。
日曜日はformat('N')で7という結果が返ってきます。7だった場合日曜日なので、tdの背景にstyle="background-color:#f08080"を追加します。
それ以外はdefaultで色は設定しません。
calendar.php

    for ($i = 1; $i <= $daysInMonth; $i++) {
        if($i==1){
            if ($dt->format('N')!= 1) {
                $calendar .= '<td colspan="'.($dt->format('N')-1).'"></td>'; //1日が月曜じゃない場合はcospanでその分あける
            }
        }

      if($dt->format('N') == 1){
          $calendar .= '</tr><tr>'; //月曜日だったら改行
      }

+     switch ($dt->format('N')) {
+         case 6:
+             $calendar .= '<td class="day" style="background-color:#b0e0e6">'.$dt->day.'</td>';
+             break;
+         case 7:
+             $calendar .= '<td class="day" style="background-color:#f08080">'.$dt->day.'</td>';
+             break;
+         default:
+             $calendar .= '<td class="day" >'.$dt->day.'</td>';
+             break;
+     }
-       $calendar .= '<td class="day">'.$dt->day.'</td>';
        $dt->addDay();
    }

チェックして、土日に色がついていればOKです。

今日を緑にする

カレンダーの中で今日がある場合、今日の背景を緑色にします。
ループ内で$dtをもとに新しいオブジェクト$compを作成し、もう一つ今日の日付を取得するオブジェクト$comp_nowを作成します。
この2つが同じだった場合、その日は今日なので色を緑(インラインでtdの背景をstyle="background-color:#008b8b"に設定)にする分岐を作成します。
calendar.php

    if($dt->format('N') == 1){
        $calendar .= '</tr><tr>'; //月曜日だったら改行
    }

+   $comp = new Carbon($dt->year."-".$dt->month."-".$dt->day); //ループで表示している日
+   $comp_now = Carbon::today(); //今日
+
+   //ループの日と今日を比較
+   if ($comp->eq($comp_now)) {
+       //同じなので緑色の背景にする
+       $calendar .= '<td class="day" style="background-color:#008b8b;">'.$dt->day.'</td>';
+   }else{
        switch ($dt->format('N')) {
            case 6:
                $calendar .= '<td class="day" style="background-color:#b0e0e6">'.$dt->day.'</td>';
                break;
            case 7:
                $calendar .= '<td class="day" style="background-color:#f08080">'.$dt->day.'</td>';
                break;
            default:
                $calendar .= '<td class="day" >'.$dt->day.'</td>';
                break;
        }
+   }

確認して今日が緑色になっていればOKです。

デザインの適用

他のコーポレートサイトページと同じデザインになるよう、メニューバーなどデザインを適用していきます。

htmlで表示

phpを閉じて、その下にshop.phpのhtml部分をコピーして貼り付けます。
titleとwrapper-titleのh3を無料ご相談会予約に変更し、pタグを削除します。
パンくずリストもTOP>無料ご相談会になるように変更します。
<div class="item-list">〜</div><!--end item-list -->までを削除します。
calendar.php

?>
<!DOCTYPE html>
<html>

<head>
    <!-- Global site tag (gtag.js) - Google Analytics -->
    <script async src="https://www.googletagmanager.com/gtag/js?id=UA-13xxxxxxxxx"></script>
    <script>
        window.dataLayer = window.dataLayer || [];
        function gtag() { dataLayer.push(arguments); }
        gtag('js', new Date());

        gtag('config', 'UA-13xxxxxxxxx');
    </script>

    <meta charset="utf-8">
    <meta http-equiv="X-UA-Compatible" content="IE=edge">
    <meta name="viewport" content="width=device-width, initial-scale=1.0">

    <title>無料ご相談会予約|SQUARE, inc.</title>

    <link rel="icon" href="favicon.ico">

    <!-- css -->
    <link rel="stylesheet" href="styles.css">
    <link rel="stylesheet" href="responsive.css">

    <!-- icon -->
    <link href="https://use.fontawesome.com/releases/v5.0.6/css/all.css" rel="stylesheet">
</head>

<body>
    <header>
        <div class="container">
            <div class="header-logo">
                <h1><a href="index.php"><img src="img/square_logo.png" id="logo"></a></h1>
            </div>

            <!-- ハンバーガーメニューボタン -->
            <div class="toggle">
                <div>
                    <span></span>
                    <span></span>
                    <span></span>
                </div>
            </div>
            <div class="cart">
                <a href="cart.php"><i class="fas fa-shopping-cart"></i></a>
            </div>

            <nav class="sp-menu menu">
                <ul>
                    <li><a href="index.php#service">サービス</a></li>
                    <li><a href="shop.php">商品一覧</a></li>
                    <li><a href="index.php#news">お知らせ</a></li>
                    <li><a href="index.php#about">会社概要</a></li>
                    <li><a href="index.php#contact">お問合せ</a></li>
                    <li><a href="ブログのURL">ブログ</a></li>
                    <?php if($user_login==true): ?>
                    <li><a href="logout.php">ログアウト</a></li>
                    <?php else: ?>
                    <li><a href="login.php">ログイン</a></li>
                    <?php endif; ?>
                </ul>
            </nav>

            <nav class="pc-menu menu-left menu">
                <ul>
                    <li><a href="index.php#service">サービス</a></li>
                    <li><a href="shop.php">商品一覧</a></li>
                    <li><a href="index.php#news">お知らせ</a></li>
                    <li><a href="index.php#about">会社概要</a></li>
                    <li><a href="index.php#contact">お問合せ</a></li>
                    <li><a href="ブログのURL">ブログ</a></li>
                </ul>
            </nav>
            <nav class="pc-menu menu-right menu">
                <ul>
                    <li><a href="cart.php"><i class="fas fa-shopping-cart"></i></a></li>
                    <?php if($user_login==true): ?>
                    <li><a href="logout.php">ログアウト</a></li>
                    <?php else: ?>
                    <li><a href="login.php">ログイン</a></li>
                    <?php endif; ?>
                </ul>
            </nav>
        </div>
    </header>
    <main>
        <div class="breadcrumbs">
            <div class="container">
                <ul>
                    <li><a href="index.php">TOP</a></li>
                    <li>無料ご相談会予約</li>
                </ul>
            </div>
        </div>
        <div class="wrapper last-wrapper">
            <div class="container">
                <div class="wrapper-title">
                    <h3>無料ご相談会予約</h3>
                </div>
            </div>
        </div>
    </main>
    <footer>
        <div class="container">
            <p>Copyright @ 2018 SQUARE, inc.</p>
        </div>
    </footer>
    <script src="https://ajax.googleapis.com/ajax/libs/jquery/3.2.1/jquery.min.js"></script>
    <script>
        $(function () {
            // ハンバーガーメニューの動作
            $('.toggle').click(function () {
                $("header").toggleClass('open');
                $(".sp-menu").slideToggle(500);
            });
        });        
    </script>
</body>

</html>

メニューバーの表示でログイン機能をつかっているので、冒頭のphpにログインチェックを追加します。
calendar.php

    <?php

+      session_start();
+      $user_login = isset($_SESSION['user_login'])? $_SESSION['user_login']:false;

        require 'vendor/autoload.php';
        use Carbon\Carbon;

カレンダーを表示させるようにします。
calender.php

    <div class="wrapper last-wrapper">
        <div class="container">
            <div class="wrapper-title">
                <h3>無料ご相談会予約</h3>
            </div>
+           <?php echo renderCalendar($dt); ?>
        </div>
    </div>

いままで表示していたカレンダーを削除します。
calendar.php

-       renderCalendar($dt);

        function renderCalendar($dt)
        {

            ~~~~省略~~~~

            calendar .= '</tr></tbody>';
            $calendar .= '</table>';

-           echo $title.$calendar;
+           return $title.$calendar;
        }

    ?>

php部分でカレンダーテーブル用のクラスを設定します。

    //曜日の配列作成
    $headings = ['Monday','Tuesday','Wednesday','Thursday','Friday','Saterday','Sunday'];

-   $calendar = '<table class="table" border=1>';
+   $calendar = '<table class="calendar-table">';
    $calendar .= '<thead >';
    foreach ($headings as $heading) {
        $calendar .= '<th class="header">'.$heading.'</th>';
    }
    $calendar .= '</thead>';

    $calendar .= '<tbody><tr>';

また、カレンダーの曜日部分が英語表記のままだと、レスポンシブにした時にスタイルが崩れてしまうので、漢字表記に変更します。
calendar.php

      //曜日の配列作成
-    $headings = ['Monday','Tuesday','Wednesday','Thursday','Friday','Saterday','Sunday'];
+    $headings = ['月','火','水','木','金','土','日'];

カレンダー上部(前月、来月リンク部分)のスタイルもいい感じになるようクラスをつけて整えます。
calendar.php

-   $title = '<caption><a href="./calendar.php?y='.$todayY.'&&m='.$todayM.'">今日 </a>';
-   $title .= '<a href="./calendar.php?y='.$subY.'&&m='.$subM.'"><<前月 </a>';//前月のリンク  
-   $title .= $dt->format('F Y');//月と年を表示
-   $title .= '<a href="./calendar.php?y='.$addY.'&&m='.$addM.'"> 来月>></a></caption>';//月と年を表示

+   $title = '<h4>'.$dt->format('F Y').'</h4>';//月と年を表示
+   $title .= '<div class="month"><caption><a class="left" href="./calendar.php?y='.$todayY.'&&m='.$todayM.'">今月 </a>';
+   $title .= '<a class="left" href="./calendar.php?y='.$subY.'&&m='.$subM.'"><<前月 </a>';//前月のリンク
+   $title .= '<a class="right" href="./calendar.php?y='.$addY.'&&m='.$addM.'"> 来月>></a></caption></div>';//来月リンク

cssも追加します。
styles.css

/* calendar.php */

.calendar-table {
    width: 100%;
    border-collapse: collapse;
    table-layout: fixed;
}
.calendar-table th,
.calendar-table td{
    border: 1px solid #ebeced;
    padding: 10px;
}

.calendar-table .header {
    background-color: #4c586f;
    color: #fff;
    font-size: 12px;
    text-align: left;
}

.month {
    text-align: center;
    width: 100%;
}

.month a {
    color: #4a80d6;
}

.left {
    float: left;
}

.right {
    float: right;
}

.day {
    height: 100px;
}

responsive.css

    /* スマホ用 */
    @media screen and (max-width: 660px) {
    ~~~省略~~~
+      /* calendar.php */
+      .calendar-table th,
+      .calendar-table td{
+          display: table-cell;
+          padding: 5px;
+      }
+   
+     .day {
+          height: 50px;
+      }
    }

確認します。
このように表示されていればOKです。

各メニューバーに追加

各ページのメニューバーに「無料ご相談会」というメニューでカレンダーにリンクするように追加します。
index.phpなど

    <header>
        <div class="container">
            <div class="header-logo">
                <h1><a href="index.php"><img src="img/square_logo.png" id="logo"></a></h1>
            </div>

            <!-- ハンバーガーメニューボタン -->
            <div class="toggle">
                <div>
                    <span></span>
                    <span></span>
                    <span></span>
                </div>
            </div>
                <div class="cart">
                    <a href="cart.php"><i class="fas fa-shopping-cart"></i></a>
                </div>

            <nav class="sp-menu menu">
                <ul>
                    <li><a href="index.php#service">サービス</a></li>
                    <li><a href="shop.php">商品一覧</a></li>
                    <li><a href="index.php#news">お知らせ</a></li>
                    <li><a href="index.php#about">会社概要</a></li>
                    <li><a href="ブログのURL">ブログ</a></li>
+                   <li><a href="calendar.php">無料ご相談会</a></li>
                    <?php if($user_login==true): ?>
                        <li><a href="logout.php">ログアウト</a></li>
                    <?php else: ?>
                        <li><a href="login.php">ログイン</a></li>
                    <?php endif; ?>
                </ul>
            </nav>

            <nav class="pc-menu menu-left menu">
                <ul>
                    <li><a href="index.php#service">サービス</a></li>
                    <li><a href="shop.php">商品一覧</a></li>
                    <li><a href="index.php#news">お知らせ</a></li>
                    <li><a href="index.php#about">会社概要</a></li>
                    <li><a href="ブログのURL">ブログ</a></li>
+                   <li><a href="calendar.php">無料ご相談会</a></li>
                </ul>
            </nav>
            <nav class="pc-menu menu-right menu">
                <ul>
                    <li><a href="cart.php"><i class="fas fa-shopping-cart"></i></a></li>
                    <?php if($user_login==true): ?>
                        <li><a href="logout.php">ログアウト</a></li>
                    <?php else: ?>
                        <li><a href="login.php">ログイン</a></li>
                    <?php endif; ?>
                </ul>
            </nav>
        </div>
    </header>

これでカレンダーは完成です。

変更したファイル名・リンク等

No. ファイル 内容
1 index.php
page.php
confirm.php
send.php
shop.php
cart.php
pay.php
pay_card.php
pay_conf.php
pay_end.php
register.php
login.php
メニューバー変更 :無料ご相談会(calendar.php)を追加

コード

https://github.com/bluecode-io/web-basic/tree/basic8-1