【この記事を読むのに必要な時間は約 18 分です。】
ドットインストールでPHPの勉強をしている。ドットインストールのPHP関連で用意されている動画レッスンを終えた後に、DEMOを見ただけでスクリプトが書けるようになるための練習。今回は、ドットインストールの動画レッスン「PHPで作るビンゴシート」-PHP(3)に続き4回目。
最初にDEMOと考え方のヒントを提示し、それだけで実際にスクリプトを書いてみよう。スクリプトを書き終わったら、完成版と見比べて答え合わせができるようにした。
今回は、「PHPで作るシンプルカレンダー」(全12回)から。
目次
Step1
今回は最初にDEMOを見るのではなく、3ステップで作っていこう。まずは、html / CSS の知識で次の画像の通り作ってみよう。
ポイント
- html5でひな形作成。
- とりあえず1行(1週間分だけ)作ろう。
- スタイリングを整えよう。
ヒント
- ドットインストールでは曜日の列にclassをyoubi_0からyoubi_6で指定してyoubi_0とyoubi_6に色を付けていたが、色付けの為だけにクラスを設定していたので、擬似クラス(first-child / last-child)を利用してみた。
- セルの結合 / colspan=”” / 結合するセル数
- 実体参照 « « / » »
Step1の答え
<!DOCTYPE html>
<html lang="ja">
<head>
<meta charset="utf-8">
<title>Calendar</title>
<style>
th {
background: #ccc;
}
th, td {
padding: 5px;
text-align: center;
border: 1px solid #eee;
}
#youbi > th:first-child,
#days > td:first-child {
color: red;
}
#youbi > th:last-child,
#days > td:last-child {
color: blue;
}
</style>
</head>
<body>
<table>
<thead>
<tr>
<th><a href="#">«</a></th>
<th colspan="5">2015-6</th>
<th><a href="#">»</a></th>
</tr>
<tr id="youbi">
<th>日</th>
<th>月</th>
<th>火</th>
<th>水</th>
<th>木</th>
<th>金</th>
<th>土</th>
</tr>
</thead>
<tbody>
<tr id="days">
<td>1</td>
<td>2</td>
<td>3</td>
<td>4</td>
<td>5</td>
<td>6</td>
<td>7</td>
</tr>
</tbody>
</table>
</body>
</html>
Step2-だいたい完成させてみよう
ポイント
- 日付関係で必要な情報は何か?
- Unix Time Stamp / strtotime()で表示したい月を設定しよう / [2000-00-01]形式
- 表示月(指定月)の最終日(日数)/ 1日の曜日
- date() / time() / mktime() / PHPマニュアルで確認
- 曜日計算 / %の活用
- if文のネスト
- for文で第3引数に複数条件を設定
- str_repeat()
- 変数の初期化
- 「.=」を使ってどんどんセルを生成しよう。
ヒント
①表示月をmktime()で作る / $_GETで ?ym=2015-06 形式にできること / 以下のように
$ym = isset($_GET['ym']) ? $_GET['ym'] : date('Y-m');
$timeStamp = strtotime ($ym . '-01');
if ($timeStamp === false) {
$timeStamp = time();
}
Step2-DEMOの完成スクリプト
<?php
// エスケープ対策
function h($s) {
return htmlspecialchars($s, ENT_QUOTES, 'UTF-8');
}
// タイムスタンプの取得(2000-00-01形式)
$ym = isset($_GET['ym']) ? $_GET['ym'] : date('Y-m');
$timeStamp = strtotime ($ym . '-01');
if ($timeStamp === false) {
$timeStamp = time();
}
// 前月、翌月GET
$prev = date('Y-m', mktime(0,0,0,date('m',$timeStamp)-1,1,date('Y',$timeStamp)));
$next = date('Y-m', mktime(0,0,0,date('m',$timeStamp)+1,1,date('Y',$timeStamp)));
// 今月の日数を取得(今月の最終日の日付を取得)
$lastDay = date('t', $timeStamp);
// 今月1日の曜日を取得
$youbi = date('w', mktime(0,0,0,date('m',$timeStamp),1,date('Y',$timeStamp)));
// セルの生成
$weeks = array();// 配列
$week = ''; // 文字列
$week .= str_repeat('<td></td>',$youbi);
for ($day = 1; $day <= $lastDay; $day++, $youbi++) {
$week .= sprintf('<td>%d</td>', $day);
if ($youbi % 7 == 6 || $day == $lastDay) {
if($day == $lastDay) {
$week .= str_repeat('<td></td>', 6 - ($youbi % 7));
}
$weeks[] = '<tr id="days">' .$week . '</tr>';
$week = '';
}
}
?>
<!DOCTYPE html>
<html lang="ja">
<head>
<meta charset="utf-8">
<title>Calendar</title>
<style>
th {
background: #ccc;
}
th, td {
padding: 5px;
text-align: center;
border: 1px solid #eee;
}
#youbi > th:first-child,
#days > td:first-child {
color: red;
}
#youbi > th:last-child,
#days > td:last-child {
color: blue;
}
</style>
</head>
<body>
<table>
<thead>
<tr>
<th><a href="?ym=<?php echo h($prev); ?>">«</a></th>
<th colspan="5"><?php echo h(date("Y", $timeStamp) . "-" . date("m", $timeStamp)); ?></th>
<th><a href="?ym=<?php echo h($next); ?>">»</a></th>
</tr>
<tr id="youbi">
<th>日</th><th>月</th><th>火</th><th>水</th><th>木</th><th>金</th><th>土</th>
</tr>
</thead>
<tbody>
<?php
foreach ($weeks as $week) {
echo $week;
}
?>
</tbody>
</table>
</body>
</html>
Step3-Classを作成 / CSSファイルを作成 して完成
カレンダーの生成に関する部分をCalendarクラスとして別ファイルにしてみよう。
ついでに、styleも別にCSSファイルにしてみよう。
メインファイル
<?php
// classファイルの呼び出し
require_once('calendar.php');
// エスケープ
function h($s) {
return htmlspecialchars($s, ENT_QUOTES, 'UTF-8');
}
// timeStamp
$ym = isset($_GET['ym']) ? $_GET['ym'] : date("Y-m");
// class Calendarのインスタンス
$cal = new Calendar($ym);
$cal->create();
?>
<!DOCTYPE html>
<html lang="ja">
<head>
<meta charset="utf-8">
<title>PHPでカレンダー</title>
<link rel="stylesheet" href="my_style.css">
</head>
<body>
<table>
<thead>
<tr>
<th><a href="?ym=<?php echo h($cal->prev()); ?>">«</a></th>
<th colspan="5"><?php echo h($cal->yearMonth()); ?></th>
<th><a href="?ym=<?php echo h($cal->next()); ?>">»</a></th>
</tr>
<tr id="youbi">
<th>日</th><th>月</th><th>火</th><th>水</th><th>木</th><th>金</th><th>土</th>
</tr>
</thead>
<tbody>
<?php
foreach ($cal->getWeeks() as $week) {
echo $week;
}
?>
</tbody>
</table>
</body>
</html>
CSSファイル
th {
background: #ccc;
}
th, td {
padding: 5px;
text-align: center;
border: 1px solid #eee;
}
#youbi > th:first-child,
#days > td:first-child {
color: red;
}
#youbi > th:last-child,
#days > td:last-child {
color: blue;
}
calendar.phpファイル
<?php
// classの作成
class Calendar {
protected $weeks =array();
protected $timeStamp;
// インスタンス初期化処理の作成
// $timeStampを$this->timeStampへ変更
public function __construct($ym) {
$this->timeStamp = strtotime ($ym . '-01');
if ($this->timeStamp === false) {
$this->timeStamp = time();
}
}
// カレンダーを生成する
public function create() {
// 今月の日数を取得(今月の最終日の日付を取得)
$lastDay = date('t', $this->timeStamp);
// 今月1日の曜日を取得
$youbi = date('w', mktime(0,0,0,date('m',$this->timeStamp),1,date('Y',$this->timeStamp)));
// セルの生成
$week = ''; // 文字列
$week .= str_repeat('<td></td>',$youbi);
for ($day = 1; $day <= $lastDay; $day++, $youbi++) {
$week .= sprintf('<td>%d</td>', $day);
if ($youbi % 7 == 6 || $day == $lastDay) {
if($day == $lastDay) {
$week .= str_repeat('<td></td>', 6 - ($youbi % 7));
}
$this->weeks[] = '<tr id="days">' .$week . '</tr>';
$week = '';
}
}
}
public function getWeeks() {
return $this->weeks;
}
public function prev() {
return date('Y-m', mktime(0,0,0,date('m',$this->timeStamp)-1,1,date('Y',$this->timeStamp)));
}
public function next() {
return date('Y-m', mktime(0,0,0,date('m',$this->timeStamp)+1,1,date('Y',$this->timeStamp)));
}
public function yearMonth() {
return date('Y-m', $this->timeStamp);
}
}
?>
PHPマニュアルを見よう
最初は何を書いているかわからないけど、とにかく疑問点があったらPHPマニュアルを見る癖をつけよう。
date()
Date関数は詳細に説明があるので是非確認しておこう。
date (PHP 4, PHP 5)
date — ローカルの日付/時刻を書式化する
string date ( string $format [, int $timestamp = time() ] )
指定された引数 timestamp を、与えられた フォーマット文字列によりフォーマットし、日付文字列を返します。 タイムスタンプが与えられない場合は、現在の時刻が使われます。 つまり timestamp はオプションであり そのデフォルト値は time() の値です。
mktime()
mktime(PHP 4, PHP 5)
mktime — 日付を Unix のタイムスタンプとして取得する
int mktime ([ int $hour = date(“H”) [, int $minute = date(“i”) [, int $second = date(“s”) [, int $month = date(“n”) [, int $day = date(“j”) [, int $year = date(“Y”) [, int $is_dst = -1 ]]]]]]] )
与えられた引数に従って UNIX のタイムスタンプを返します。 このタイムスタンプは、Unix epoch(1970年1月1日00:00:00 GMT)から 指定された時刻までの通算秒を表す長整数です。
引数は右から順に省略することができます。省略された引数は、 ローカルの日付と時刻に従って、現在の値にセットされます。
strtotime()
strtotime(PHP 4, PHP 5)
strtotime — 英文形式の日付を Unix タイムスタンプに変換する
int strtotime ( string $time [, int $now = time() ] )
この関数は英語の書式での日付を含む文字列が指定されることを期待しており、 now で与えられたその形式から Unix タイムスタンプ (1970 年 1 月 1 日 00:00:00 UTC からの経過秒数) への変換を試みます。
以上