【PHP講座】カレンダーを作成する No.4

カレンダーを作成する

PHP でカレンダーを作成します。

前回の続きです。

【PHP講座】カレンダーを作成する No.3

2019.10.31

今回は、リンクを動作させるための仕組みをつくっていきます。



カレンダーを作成する

カレンダーを作成します。

今回の記事のポイントです。

  • リンクを動作させるための準備をする
  • 前月、翌月のリンクを作成する

それでは見ていきましょう。

リンクを動作させる準備をする

それでは、リンクを動作させるための準備をしていきます。

前回のコードの一番先頭部分に以下のコードを追記していきます。

try {
  if(!isset($_GET['t']) || !preg_match('/\A\d{4}-\d{2}\z/', $_GET['t'])){
    throw new Exception();
  }
  $thisMonth = new DateTime($_GET['t']);
} catch (Exception $e) {
  $thisMonth = new DateTime('first day of this month');
}

ポイントは、以下のコードです。

$thisMonth = new DateTime($_GET['t']);

これに対して、try~catch文を使っています。

例外が発生した場合は、以下のコードを実行します。

$thisMonth = new DateTime('first day of this month');

パラメータである t が正しく取得できないパターンを想定して if文を使っています。

このパターンに当てはまる場合、例外処理へ投げます。

値が入っているか、数字4桁と -(ハイフン)と数字2桁の組合せになっているかを調べています。

前月、翌月のリンクを作成する

前月、翌月のリンクを作成していきます。

前回のコードの HTML 部分を修正していきます。

<thead>
  <tr>
    <th><a href="/?t=<?php echo escapeHtml($prev); ?>">«</a></th>
    <th colspan="5"><?php echo escapeHtml($yearMonth); ?></th>
    <th><a href="/?t=<?php echo escapeHtml($next); ?>">»</a></th>
  </tr>
</thead>

ここは、カレンダーの表示部分になります(何年何月のところ)。

escapeHtml という関数を自作して、エスケープ処理をします。

function escaptHtml($s) {
  return htmlspecialchars($s, ENT_QUOTES, 'UTF-8');
}

htmlspecialchars関数を使って、HTML にとっての特殊文字を表示できるように変換しています。

続いて、肝心の prev と next の値をつくっていきます。

$dt = clone $thisMonth;
$prev = $dt->modify('-1 month')->format('Y-m');
$dt = clone $thisMonth;
$next = $dt->modify('+1 month')->format('Y-m');

$yearMonth = $thisMonth->format('F Y');

modify で、タイムスタンプを変更しています。

あとは、2019-11 というような形式、数字4桁(年)- 数字2桁(月)になるようにしています。

今回の記事のサンプルコード

今回の記事のサンプルです(PHP)。

スタイルシートに関しては、前回同様なので、第1回目のものをご参照ください。

<?php

function escapeHtml($s) {
  return htmlspecialchars($s, ENT_QUOTES, 'UTF-8');
}

try {
  if(!isset($_GET['t']) || !preg_match('/\A\d{4}-\d{2}\z/', $_GET['t'])){
    throw new Exception();
  }
  $thisMonth = new DateTime($_GET['t']);
} catch (Exception $e) {
  $thisMonth = new DateTime('first day of this month');
}

$dt = clone $thisMonth;
$prev = $dt->modify('-1 month')->format('Y-m');
$dt = clone $thisMonth;
$next = $dt->modify('+1 month')->format('Y-m');

$yearMonth = $thisMonth->format('F Y');

$tail = '';
$PreMonthDay = new DateTime('last day of ' . $yearMonth . ' -1 month');
while ($PreMonthDay->format('w') < 6) {
  $tail = sprintf('<td class="except">%d</td>', $PreMonthDay->format('d')) . $tail;
  $PreMonthDay->sub(new DateInterval('P1D'));
}

$content = '';
$daterange = new DatePeriod(
  new DateTime('first day of ' . $yearMonth),
  new DateInterval('P1D'),
  new DateTime('first day of ' . $yearMonth . ' +1 month')
);

foreach ($daterange as $day) {
  if ($day->format('w') % 7 === 0) {
    $content .= '</tr><tr>';
  }
  $content .= sprintf('<td class="week_%d">%d</td>', $day->format('w'), $day->format('d'));
}

$head = '';
$nextMonthDay = new DateTime('first day of ' . $yearMonth . ' +1 month');
while ($nextMonthDay->format('w') > 0) {
  $head .= sprintf('<td class="except">%d</td>', $nextMonthDay->format('d'));
  $nextMonthDay->add(new DateInterval('P1D'));
}

?>
<!DOCTYPE html>
<html lang="ja">
<head>
  <meta charset="utf-8">
  <title>My Calendar</title>
  <link rel="stylesheet" href="css/style.css">
</head>
<body>
  <table>
    <thead>
      <tr>
        <th><a href="?t=<?php echo escapeHtml($prev); ?>">«</a></th>
        <th colspan="5"><?php echo escapeHtml($yearMonth); ?></th>
        <th><a href="?t=<?php echo escapeHtml($next); ?>">»</a></th>
      </tr>
    </thead>
    <tbody>
      <tr>
        <td>Sun</td>
        <td>Mon</td>
        <td>Tue</td>
        <td>Wed</td>
        <td>Thu</td>
        <td>Fri</td>
        <td>Sat</td>
      </tr>
      <tr>
      <?php echo $tail . $content . $head; ?>
      </tr>
    </tbody>
    <tfoot>
      <tr>
        <th colspan="7"><a href="?t=test">Today</a></th>
      </tr>
    </tfoot>
  </table>
</body>

Today のリンク部分はとりあえず、今回の例外処理のテストをしています(次回以降また変更します)。

最後に

いかがでしょうか。

次回は細かい修正をしていき完成を目指したいと思っています。

最近、ドラクエウォークにハマってしまっている管理人ですが、日々勉強していきます。