かもメモ

自分の落ちた落とし穴に何度も落ちる人のメモ帳

PHP Carbonを使って週表示のカレンダーを作りたい。

週だけ表示できる良い感じのカレンダーが見つからなかったのでPHPで作ってみました。
日付の処理はLaravelでも使用されているCarbonが便利らしいので、これを使うことにしました。

仕様

  • 簡易に曜日と日付が表示できればOK
  • 週の始めは月曜 / 日曜
  • 前後で月が変わる部分も表示する

CarbonをComposerでインストー

$ composer require nesbot/carbon

週カレンダーを作成するスクリプト

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

/**
 * 週カレンダーの配列を返す関数
 * @param: $startSun(:Boolean)
 *         true ... 日曜から始める
 *         false ... 月曜から始める
 * @param: $date(:String) ... 今日の日付
 */
function getWeekCalender($isStartSun = true, $date = "") {
  $today = new Carbon( $date );
  $todayDay = $today->day;
  $startDate = getStartDay( $today->toDateString("Y-m-d"), $isStartSun );
  $startDay = $startDate->day;
  // 週の最終日を取得
  // note. コピーを作成しないと元のインスタンスの値が変更される
  $lastDay = $startDate->copy()->addDay(7)->day;

  // 開始日のある月の最終日を取得
  $limitDay = $startDate->copy()->endOfMonth()->day;

  $month = $startDate->month;
  $offset = $limitDay - $startDay;
  $day = $startDay;
  $weekArr = [];
  $i = 0;
  while($i < 7) {
    $day = $startDay + $i;
    // 月を跨いだ時
    if( $day > $limitDay ) {
      $day = $i - $offset;
      if($day === 1) {
        $month += 1;
      }
      if($month > 12) {
        $month = 1;
      }
    }
    if($isStartSun) {
      $week = getWeekByIndex($i);
    } else {
      $week = getWeekByIndex($i+1);
    }
    $weekArr[] = [
      'month' => $month,
      'day'   => $day,
      'week'  => $week,
      'today' => $todayDay === $day? true : false,
    ];
    $i++;
  }

  return $weekArr;
}

/**
 * 週の最初の日を取得
 * @param $today(:String) "Y-m-d"
 */
function getStartDay($today, $isStartSun) {
  $dt = new Carbon( $today );

  // $today が週の内何日目か (Sun = 0)
  $w = $dt->dayOfWeek;

  // 月曜始まりのとき
  if( !$isStartSun ) {
    // 今日が日曜なら前の月曜
    if($w === 0) {
      $w = 7;
    }
    $w -= 1;
  }

  return $dt->subDay( $w );
}

function getWeekByIndex($i) {
  $arr = ['Sun.', 'Mon.', 'Tue.', 'Wed.', 'Thu.', 'Fri.', 'Sat.'];
  $len = count($arr);
  if($i >= $len) {
    $i -= $len;
  }
  return $arr[$i];
}

使い方

<?php
// 今日の日付を指定する場合は第ニ引数で指定
// ex: 月曜始まり 2017年3月3日 のある週カレンダー
$weekCalenderData = getWeekCalender(false, "2017-03-03");

// カレンダーを出力
foreach($weekCalenderData as $val) {
  $th .= "<th>{$val['week']}</th>\n";
  $td .= "<td>{$val['day']}</td>\n";
}
echo "<table><tr>${th}</tr><tr>{$td}</tr></table>";

↓ 出力

Mon. Tue. Wed. Thu. Fri. Sat. Sun.
27 28 1 2 3 4 5

感想とか

Carbon は月末日とか簡単に取得できて凄い便利なのですが、関数を使うと元のオブジェクトの日付が変更されてしまう破壊的メソッド(?)なので、元の日付から色々計算した日付を取得したい時はcopy()メソッドを噛ませてオブジェクトを複製しないとハマりそうだなって思いました。


Signalize!/カレンダーガール

Signalize!/カレンダーガール