PHPで作る月間予定カレンダ
ー(monthly-schedule)

「今月のスケジュールを◯✗△で表示するページが欲しい」と思い、単純なHTMLページを作りました。
その後、管理者がデータを更新できる本格的なシステムになりました。

関連記事

1. 試作:JavaScriptによるカレンダー

まず、動的に更新できるページとして作成しました。

https://chiilabo.jp/monthly-schedule/simple-version/
https://chiilabo.jp/monthly-schedule/simple-version/

ローカルストレージを使ったシンプルなカレンダーでした。
各日付をクリックすると、◯(予定あり)→ ✗(予定なし)→ △(未定)→ 空白、という順番でステータスが切り替わります。
データはブラウザのローカルストレージに保存されるため、ページを閉じても情報は残ります。

ただし、このバージョンには大きな問題がありました。
訪問者全員が自分用のカレンダーを作れることになります。

1.1. ナビゲーション機能の追加

次に、次の月、前の月に移動できるようにしました。displayYeardisplayMonthという変数を導入し、月の移動を管理する仕組みを実装しました。前月・次月ボタンをクリックすると、これらの変数が更新され、カレンダーが再描画されます。
同時に、最終更新日時の表示形式も「YYYY-MM-DD hh:00」に変更するようしました。

2. システムの再設計

次に、月間カレンダーとして書き直しました。
新しいシステムは3つのPHPファイルで構成されています。

config.phpは、システム全体の設定を管理します。
管理画面のパスワード、データファイルのパス、そしてデータの読み書きを行う関数が定義されています。
特に重要なのがcleanOldData()関数で、これは過去の日付のデータを自動的に削除します。
予約システムでは、過ぎた日のデータは不要なので、この機能は便利です。

admin.phpは管理者専用ページです。
最初にパスワード認証があり、正しいパスワードを入力しないと先に進めません。
ログイン後は、カレンダー形式で各日付のステータスを設定できます。

index.phpは一般公開用のページです。
誰でもアクセスでき、現在の予約状況を確認できます。月の移動ボタンもあり、先の予約状況まで確認可能です。フッターには最終更新日時が表示されます。

2. システムの再設計

2.1. データの永続化:JSONファイルの活用

このシステムでは、データベースを使わず、JSONファイルにデータを保存しています。schedule_data.jsonというファイルに、日付をキーとしたステータスが記録されます。

{
  "2026-01-15": "maru",
  "2026-01-16": "sankaku",
  "2026-01-20": "batsu",
  "_updated_at": "2026-01-02 15:00"
}
Code language: JSON / JSON with Comments (json)

JSONファイルを選んだのは、小規模なシステムには十分な性能があり、データベースの設定が不要だからです。ただし、同時に複数の管理者が更新する場合は、最後に保存した人のデータで上書きされてしまう点には注意が必要です。

3. config.phpの保護

このシステムにはいくつかのセキュリティ上の考慮点があります。
最も重要なのは、パスワードが記述されたconfig.phpを保護することです。

パスワードはconfig.phpにハードコーディングされているため、このファイルは絶対にWebから直接アクセスできないようにする必要があります。

通常、ブラウザでconfig.phpにアクセスしても、画面には何も表示されません。PHPコードは実行されますが、画面に出力するecho文がないため、結果は空白です。

3. config.phpの保護

「なら大丈夫では?」と思うかもしれません。しかし、これは非常に危険な考えです。サーバーの設定ミスやトラブルで、PHPが実行されずにソースコードがそのまま表示されることがあるからです。

たとえば、PHPモジュールが無効化されたり、サーバー移行時の設定が不完全だったりすると、ブラウザに以下のように表示されます。

<?php
define('ADMIN_PASSWORD', 'admin123');  // パスワードが丸見え
Code language: HTML, XML (xml)

また、エディタやデプロイツールが自動作成するバックアップファイル(config.php.bakconfig.php~)は、PHPとして実行されず、テキストファイルとしてダウンロード可能になる場合があります。

3.1. 第1層:.htaccessによるアクセス制限

Apacheサーバーを使っている場合、.htaccessファイルで特定のファイルへのアクセスを拒否できます。

<Files "config.php">
    Order Allow,Deny
    Deny from all
</Files>

<Files "schedule_data.json">
    Order Allow,Deny
    Deny from all
</Files>
Code language: HTML, XML (xml)

このファイルをindex.phpと同じディレクトリに配置すると、ブラウザからconfig.phpにアクセスしようとしても、403 Forbiddenエラーが返されます。

3.1. 第1層:.htaccessによるアクセス制限

データファイルであるschedule_data.jsonも同様に保護します。

注意点として、ファイル名は.htaccessであり、先頭にドット(.)が必要です。このファイルは多くのFTPソフトでは「隠しファイル」として扱われるため、アップロード時には「隠しファイルを表示」設定をオンにする必要があります。

3.2. 第2層:ファイルパーミッションの設定(600)

セキュリティの基本は「何層にも防御を重ねる」ことです。
.htaccessが何らかの理由で機能しない環境もあるからです。

config.phpschedule_data.jsonには、chmod 600を設定しました。

3.2. 第2層:ファイルパーミッションの設定(600)
chmod 600 config.php
chmod 600 schedule_data.json
Code language: CSS (css)

Linuxサーバーでは、各ファイルに「誰が何をできるか」を示すパーミッションが設定されています。
「600」という数値は「所有者のみが読み書き可能」を意味します。
Webサーバーのプロセスは所有者として実行されるため正常に動作しますが、他のユーザーからは見えません。

FTPソフトを使う場合は、ファイルを右クリックして「パーミッション」メニューから数値で600を入力できます。レンタルサーバーのファイルマネージャーでも同様の操作が可能です。

4. システムの実用性と限界

完成したシステムは、小規模な予約管理には十分実用的です。美容室、教室、施設の予約状況公開など、様々な用途に使えます。

ただし、いくつかの限界もあります。データベースを使っていないため、大量のデータや複雑な検索には向きません。また、予約の詳細情報(予約者名、連絡先など)を管理する機能はありません。あくまでも「空き状況の表示」に特化したシステムです。

より高度な機能が必要な場合は、WordPressのプラグインや、専門の予約管理サービスを検討すべきでしょう。しかし、シンプルさと軽量さを重視するなら、このシステムは良い選択肢となります。