第19回 スケジューラーを作ろう(9) - スケジューラー完成 - - PHP基礎講座
Saity先生のPHP基礎講座
Lecutures on PHP
第19回 スケジューラーを作ろう(9) - スケジューラー完成 - (その1)
- あの~、先生。(そわそわ)
- ん?どうしたんだい?
- 先生は甘いものは好きですか?
- (おっ?)うん、甘いものは大好きかな☆
- そ、それじゃあ、このケーキ食べてみてください!
- おお~、いいのかい?それじゃ早速・・・(ぱくっ)・・・・(うっxx!)
- どきどき。。。ど、どうですか??
- ・・・(もぐもぐ)・・・・(ごくん)・・・・あ、ありがとう!お、ぉぃしいょ!
- やったー♪それじゃあ今度から、もっと色々作ってきますね!!!
- ほ、本当に?!あ、あはは・・・。
別の月も表示できるようにしよう
- さて、気を取り直して、今回はスケジューラーをもう少し改良していこう。
- ん??何の気を取り直すんだろう。。。。うーん、このスケジューラーのカレンダーって、今の月の表示しか出来ないのって、すごく不便ですね。。。

- 確かに今のままでは来月の予定を登録しても見ることは出来ないね。カレンダーに表示する月を変更出来るように、コードを作り変えていこう。さて、どこを変えていけばいいのか、わかるかい?
- 以前作ったschedule_calendar.phpの中では、年月を指定するのに全部date関数を使ってましたね。第一引数だけを指定するようにして、今の月を取ってきてたわね。
- うんうん。前回作ったコードは、以下のようになっていたよね。
<?php
$first_date = mktime(0, 0, 0, date("m"), 1, date("Y"));
$last_date = mktime(0, 0, 0, date("m") + 1, 0, date("Y"));
// 最初の日と最後の日の「日にち」の部分だけ数字で取り出す。
$first_day = date("j", $first_date);
$last_day = date("j", $last_date);
// 全ての日の曜日を得る。
for($day = $first_day; $day <= $last_day; $day++) {
$day_timestamp = mktime(0, 0, 0, date("m"), $day, date("Y"));
$week[$day] = date("w", $day_timestamp);
}
?>
<html>
<head>
<title>カレンダー</title>
</head>
<body>
<table border="1">
<tr>
<th>日</th>
<th>月</th>
<th>火</th>
<th>水</th>
<th>木</th>
<th>金</th>
<th>土</th>
</tr>
<tr>
<?php
// カレンダーの最初の空白部分
for ($i = 0; $i < $week[$first_day]; $i++) {
print ("<td></td>\n");
}
for ($day = $first_day; $day <= $last_day; $day++) {
if ($week[$day] == 0) {
print ("</tr>\n<tr>\n");
}
print ("<td><a href=\"schedule_list.php?year=" .date("Y") .
"&month=". date("m") . "&day=$day\">$day</a></td>\n");
}
// カレンダーの最後の空白部分
for ($i = $week[$last_day] + 1; $i < 7; $i++) {
print ("<td></td>\n");
}
?>
</tr>
</table>
<a href="schedule_edit.php">スケジュールの新規作成</a>
</body>
</html>
- そうそう!だから、このコードのdate("m")とdate("Y")となっている部分に全部、表示したい年月を第二引数として指定するように書き換えてあげればいいんですよ!
- そうだね。でも全部書き換える前にちょっと待って。
- およよ?
- これらは全部、重複した処理をしてしまってる部分だよね。このまま書き換えてしまうと、何度も同じ関数を使って同じ結果を取得するってことになるけど、それってとてもが効率悪いよね。

- ふむー、確かに。。。
- そこで、これらの部分をそれぞれ変数に置き換えてしまおう。こうやって無駄な処理を減らすことを心がけると、結果的にコードが読みやすくなって、きれいなプログラムが出来るようになるよ。
- なるほどー。そういう心がけも必要なんですね。
- さて、それじゃ今の話を踏まえて、カレンダーを作り変えてあげよう。
- はーい。 こんなかんじかな。。。えいえい(ササササ)
<?php
// カレンダーの年月をタイムスタンプを使って指定
if (isset($_GET["date"]) && $_GET["date"] != "") {
$date_timestamp = $_GET["date"];
} else {
$date_timestamp = time();
}
$month = date("m", $date_timestamp);
$year = date("Y", $date_timestamp);
$first_date = mktime(0, 0, 0, $month, 1, $year);
$last_date = mktime(0, 0, 0, $month + 1, 0, $year);
// 最初の日と最後の日の「日にち」の部分だけ数字で取り出す。
$first_day = date("j", $first_date);
$last_day = date("j", $last_date);
// 全ての日の曜日を得る。
for($day = $first_day; $day <= $last_day; $day++) {
$day_timestamp = mktime(0, 0, 0, $month, $day, $year);
$week[$day] = date("w", $day_timestamp);
}
?>
<html>
<head>
<title>カレンダー</title>
</head>
<body>
<table border="1">
<tr>
<th>日</th>
<th>月</th>
<th>火</th>
<th>水</th>
<th>木</th>
<th>金</th>
<th>土</th>
</tr>
<tr>
<?php
// カレンダーの最初の空白部分
for ($i = 0; $i < $week[$first_day]; $i++) {
print ("<td></td>\n");
}
for ($day = $first_day; $day <= $last_day; $day++) {
if ($week[$day] == 0) {
print ("</tr>\n<tr>\n");
}
print ("<td><a href=\"schedule_list.php?year=" .$year .
"&month=". $month . "&day=$day\">$day</a></td>\n");
}
// カレンダーの最後の空白部分
for ($i = $week[$last_day] + 1; $i < 7; $i++) {
print ("<td></td>\n");
}
?>
</tr>
</table>
<a href="schedule_edit.php">スケジュールの新規作成</a>
</body>
</html>
- できたー!$_GET["date"]でタイムスタンプを受け取るようにして、特に指定がないときは今月を表示するようにしてみました☆
- お、タイムスタンプが「数値」だっていうことをきちんと覚えていたね。しかもtime関数なんて見つけてくるとは、やるねぇ。
- date関数のマニュアルに書いてありましたから♪time関数は今現在のタイムスタンプを返すんですよね。
- あとは、年月の表示と前の月、次の月のセレクターをつければOKだね。
- う。。。それなんですが。。。実は、適切な関数が見つからなくて困ってるんです・・・orz

- ふむ。じゃあちょっと助け舟を出すとしようか。 タイムスタンプを簡単に操作するのに適した関数の一つに、strtotime関数があるよ。マニュアルの例のところを見てごらん。
- ほうほぅ。なんか、わかりやすいようなわかりにくいような。。。普通の言葉みたいな指定が出来るのかな?
- 確かに、慣れないとわかりにくいかもね。例の"+1 day", "+1 week"などと同じ要領で、第一引数に"+1 month"と指定してあげれば、きちんと次の月のタイムスタンプを返してくれるよ。逆に"-1 month"を指定すれば、前の月のタイムスタンプが得られるって寸法だ。
- おおー!これ一個で全部済んじゃうとは、さすが。。。これで望みどおりのセレクターが作れそうだわ。
- よし、じゃあざざざーっと作ってあげよう。
<!-- カレンダー部分のみ抜粋 -->
<html>
<head>
<title>カレンダー</title>
</head>
<body>
<table border="1">
<tr>
<th colspan="2"><a href="schedule_calendar.php?date=
<?php print (strtotime("-1 month", $first_date)); ?>">前月</a></th>
<th colspan="3"><?php print (date("Y", $date_timestamp) . "年" . date("n", $date_timestamp) . "月"); ?></th>
<th colspan="2"><a href="schedule_calendar.php?date=
<?php print (strtotime("+1 month", $first_date)); ?>">次月</a></th>
</tr>
<tr>
<th>日</th>
<th>月</th>
<th>火</th>
<th>水</th>
<th>木</th>
<th>金</th>
<th>土</th>
</tr>
- あれ?なんで「前月」と「次月」のところで$first_dateをつかったの??$date_timestampじゃだめなんですか?
- 月末のことを考えるとよくわかるよ。もし、1月31日に「次月」を考えると、どうなるかな?
- あ、そっか。。。2月31日はないし、よくわからないことになるわね。だから、ややこしくならないように月の最初の日を使ったのかぁ。
- さすが、飲み込みが早いね。まさにそういう事☆なにはともあれ、これで今月以外も見られるようになったね。
- そうですねー。でも、これじゃどの日に予定が入っているかわからなくて、役に立たない。。。
- うんうん。それじゃあ、 予定が入っている日にだけリンクをつけるように作り変えようか。
- ふむぅ。確かに、そうなればずっと便利ですね。またfile関数で読み込んだデータを使うのかな?
- うん。基本的にはschedule_list.phpで行ったことと似たような処理をすることになるね。読み込んだデータの日付を見て、その日に登録があればリンクをつけるようにすればいいね。
- よぅし、ちゃちゃっと作ってみるかな。。。。
- よく書けるようになったなぁ・・・(しみじみ)

- まず登録されているスケジュールと指定した年月日を比較して、ヒットしたらリンクをつけるようにしてみましたー。
- 無駄な処理をしないようにbreakもあるし、いいんじゃないかな。
- やったー☆
// スクリプト部分のみ抜粋
// カレンダーの最初の空白部分
for ($i = 0; $i < $week[$first_day]; $i++) {
print("<td></td>\n");
}
$filename = "samplefile.txt";
$schedule_list = file($filename);
for ($day = $first_day; $day <= $last_day; $day++) {
if ($week[$day] == 0) {
print("</tr>\n<tr>\n");
}
// スケジュールが存在するかどうかチェックする
$exist_schedule = false;
foreach ($schedule_list as $lineno => $line) {
list($schedule_date, $title, $body) = explode("|", $line);
if ($schedule_date
== $year . $month . sprintf("%02d", $day)) {
$exist_schedule = true;
break;
}
}
// スケジュールが存在したらリンクをつける
if ($exist_schedule) {
print("<td><a href=\"schedule_list.php?year=" .$year .
"&month=". $month . "&day=$day\">$day</a></td>\n");
} else {
print("<td>$day</td>\n");
}
}
// カレンダーの最後の空白部分
for ($i = $week[$last_day] + 1; $i < 7; $i++) {
print("<td></td>\n");
}
?>
- 1
- 2





ページのトップへ


kende様のご指摘通り、三項演算子を使用する際には、コードの複雑度などを考慮する必要がありますね。書きやすさと共に可読性も追求したいところですね。