Webサイトの「ちょっとした更新」で困っていませんか?
Webサイトを運営していると、お知らせ、イベント情報、商品リストなど、頻繁に更新が必要な箇所が出てきますよね。WordPressのようなCMS(コンテンツ管理システム)を導入していれば問題ありませんが、静的なHTMLサイトや小規模なプロジェクトでは、「この部分だけ更新したい」というニーズのためにCMSを導入するのは大掛かりすぎます。
かといって、更新のたびにWeb制作者がFTPでファイルを修正したり、ましてやクライアントに「ソースコードのこの部分を書き換えてください」とお願いするのは、ソースコードを壊されるリスクもあり、現実的ではありません。
そんな時、「特定のデータ(JSONファイル)だけを、Webの画面上から安全に更新できるツール」があれば便利だと思いませんか?
この記事では、PHPとjQuery(jQuery UI)を使い、ブラウザからJSONファイルを直接編集できる「簡易CMS」の作り方を、デモとソースコード付きで詳しく解説します。
完成デモ
まずは、どのようなものができるのか、実際のデモを触ってみてください。ドラッグ&ドロップでの並べ替えや、新規追加・削除が直感的に行えることが分かるはずです。
主な機能
この簡易CMSで実現できる主な機能は以下の通りです。
- JSONデータの表示: 既存のJSONデータを読み込み、編集可能なフォームとして表示します。
- 新規要素の追加: 「新規作成」ボタンで、新しいデータブロックを追加できます。
- 要素の削除: 各ブロックの「削除」ボタンで、不要なデータを削除できます。
- 並べ替え: jQuery UIの
sortableを使い、ドラッグ&ドロップでデータの順番を簡単に入れ替えられます。 - 更新(保存): 「更新する」ボタンで、編集内容をサーバー上のJSONファイルに保存(書き込み)します。
実装方法とコード解説
このツールは、主にPHP(サーバーサイド)とJavaScript(クライアントサイド)の2つの技術で成り立っています。必要なファイルは、PHPファイル(HTMLとJSも内包)と、データの保存先となるJSONファイルの2つだけです。
※jQueryとjQuery UIライブラリをCDNなどで読み込んでいることが前提です。
<!-- jQueryとjQuery UIの読み込み例 -->
<script src="https://ajax.googleapis.com/ajax/libs/jquery/3.7.0/jquery.min.js"></script>
<script src="https://ajax.googleapis.com/ajax/libs/jqueryui/1.12.1/jquery-ui.min.js"></script>
以下、主要なコードを「PHP編」「HTML編」「JavaScript編」に分けて解説します。(※デモでは1つのPHPファイルにすべて記述されています)
1. PHP編:JSONの読み込みと書き込み
サーバーサイド(PHP)では、JSONファイルの読み込み(file_get_contents)と、ブラウザから送られてきたデータの書き込み(file_put_contents)という、2つの重要な処理を行います。
<?php
$jsonUrl = "./cmsTest.json"; //JSONファイルの場所とファイル名を記述
//【1. JSONファイルをHTMLに変換する関数】
function echoJson($jsonUrl, $tablClass) {
if (file_exists($jsonUrl)) { //JSONファイルが存在したら
$json = file_get_contents($jsonUrl); //中身を取り出し
$json = mb_convert_encoding($json, 'UTF8', 'ASCII,JIS,UTF-8,EUC-JP,SJIS-WIN'); //エンコードして
$obj = json_decode($json, true); //PHP用の配列に直して
$i = 1;
foreach ($obj as $key => $val) { //HTMLを作成
echo '<div id="block-' . $i . '" class="block-article" draggable="true">';
echo '<h2>' . htmlspecialchars($val['title'], ENT_QUOTES, 'UTF-8') . '</h2>'; // XSS対策
echo '<table class="' . htmlspecialchars($tablClass, ENT_QUOTES, 'UTF-8') . '">';
foreach ($val as $key => $value) {
// XSS対策のため htmlspecialchars を適用
$key_esc = htmlspecialchars($key, ENT_QUOTES, 'UTF-8');
$value_esc = htmlspecialchars($value, ENT_QUOTES, 'UTF-8');
echo '<tr><th class="js-th">' . $key_esc . '</th><td class="js-td -' . $key_esc . '"><input required type="text" value="' . $value_esc . '"></td></tr>';
}
echo '</table>';
echo '<div class="btn_wrap -delete"><a class="button js-btnDeleteArticle">削除</a></div>';
echo '</div>';
$i++;
}
} else { //JSONファイルがなければエラー表記
echo "<p class='errorTxt'>データがありません</div>";
}
}
//【2. POSTリクエスト(フォーム送信)があった時の処理】
if ($_SERVER['REQUEST_METHOD'] == 'POST') {
if ($_POST['json'] == null) { //$_POST['json']が空ならエラーメッセージ表示
echo '<p class="errorTxt">入力してください。</p>';
} else {
// file_put_contentsでJSONを書き出す
$result = file_put_contents($jsonUrl, $_POST['json']);
if ($result) { //書き出しの結果をHTMLに出力
echo '<p class="dialog successTxt">書き込みました</p>';
} else {
echo '<p class="dialog errorTxt">書き込みできませんでした</p>';
}
}
}
?>
ポイント解説:
echoJson()関数は、JSONファイルをPHPの配列に変換(json_decode)し、foreachでループさせてHTMLのテーブル(編集フォーム)を生成しています。- POST送信時、
file_put_contentsという関数が、送信されてきたJSON文字列($_POST['json'])を、指定したファイル($jsonUrl)に上書き保存します。この「PHPによるファイル書き込み」が、このツールの核心部分です。 - (※元のコードに対し、セキュリティ(XSS対策)のため
htmlspecialcharsを追加しています)
2. HTML編:編集フォームの骨組み
ブラウザに表示される画面の骨組みです。PHPを呼び出す箇所と、JavaScriptが操作する対象(IDやクラス)がポイントです。
<div class="inner">
<h1>file_put_contents test</h1>
<!-- 新規作成ボタン -->
<div class="btn_wrap -create">
<div class="chk_view" id="create"></div>
<button id="createArticle">新規作成</button>
</div>
<!-- 更新フォーム -->
<form id="js-form-campaign" class="form-campaign" action="" method="POST">
<!-- JavaScriptによって生成されたJSON文字列がここに入る -->
<input id="js-exportjson" type="hidden" name="json" value="初期値">
<!-- JSONデータが表示され、並べ替え可能になるエリア -->
<div id="sortable">
<?php echoJson($jsonUrl, 'tableCampaign'); ?>
</div>
<!-- 更新ボタン -->
<div class="btn_wrap -update">
<div class="chk_view" id="update"></div>
<button type="submit">更新する</button>
</div>
</form>
<h2>jsonの中身(確認用)</h2>
<iframe src="./cmsTest.json" frameborder="0" style="width: 100%; height: 300px;"></iframe>
</div>
ポイント解説:
<form>タグで全体を囲み、method="POST"で送信します。action=""は、自分自身のページに送信することを意味します。<div id="sortable">の中で、先ほどのPHP関数echoJson()を呼び出し、現在のJSONデータに基づいたフォームを表示しています。<input id="js-exportjson">はtype="hidden"です。ここには、ユーザーが「更新」ボタンを押した瞬間にJavaScriptが生成する「最新のJSON文字列」が格納され、PHP側に送信されます。
3. JavaScript (jQuery) 編:操作とJSONの生成
ブラウザ上でのユーザー操作(新規作成、削除、並べ替え)と、PHPに送信するためのJSONデータを生成する処理を担当します。
<script>
/* 1. 新規作成ボタンを押した時、記事を追加 */
$('#createArticle').on('click', function() {
let content_area = $('.block-article').first(); //最初のブロックを選択
let clone_element = content_area[0].cloneNode(true); //選択したブロックをクローン
let h2_element = clone_element.querySelector("h2"); //クローンしたブロックの見出しのテキストを変更
h2_element.textContent = '新規コンテンツ';
let ttl_element = clone_element.querySelectorAll(".js-td input"); //クローンしたブロックのinputを空にする
ttl_element.forEach(function(element) { element.value = '' });
content_area.before(clone_element); //クローンした要素を一番先頭に挿入する
window.scroll({ top: 0, behavior: 'smooth' }); //先頭までスクロール
});
/* 2. 削除ボタンを押した時、記事を削除 */
$(document).on("click", ".js-btnDeleteArticle", function() {
var result = confirm('本当に削除しますか。'); //削除するか確認する
if (result) {
$(this).parents('.block-article').remove(); //ブロックを削除
alert('削除しました');
}
});
/* 3. ドラッグ&ドロップで並べ替え (jQuery UI) */
$("#sortable").sortable({
axis: "y" // 縦方向のみに制限
});
/* 4. submitボタンを押した時、送信用のJSONを作成 */
$('#js-form-campaign').on('submit', function() {
const tableElement = $('.tableCampaign');
let exportDataArray = []; //出力用データの配列を用意
tableElement.each(function(index) { //table(各ブロック)の数だけ処理を実行
let matome = {}; //出力用データに送る前のオブジェクトをここでまとめる
$(this).find('tr').each(function(index) { //tr(各項目)の数だけ処理を実行
let thText = $(this).children('.js-th').text(); //thのテキスト(JSONのキー)を変数に追加
let tdValue = $(this).find('.js-td input').val(); //tdのinput値(JSONのバリュー)を変数に追加
matome[thText] = tdValue; // {キー: バリュー} の形で matome{} に追加
});
exportDataArray.push(matome); //まとめたオブジェクトを出力用データの配列にpush
});
//出力用データの配列をJSON文字列化
let exportJsonData = JSON.stringify(exportDataArray, null, 1);
//POST送信用の隠しInput(js-exportjson)のValueを、今作ったJSON文字列で書き換え
$('#js-exportjson').val(exportJsonData);
});
/* (デモ用のスクロールエフェクト等は省略) */
</script>
ポイント解説:
- 新規作成: 既存のブロックを
cloneNode(true)で複製し、中身を空にしてから先頭に追加しています。 - 削除:
$(this).parents('.block-article').remove()で、押されたボタンの親であるブロックごとDOMから削除します。 - 並べ替え: jQuery UIの
sortable()メソッドを呼び出すだけで、id="sortable"の範囲がドラッグ&ドロップ可能になります。 - 更新(JSON生成): これが最も重要です。フォーム送信時(
on('submit'))、画面に表示されている全ての.tableCampaign(各ブロック)をeachで走査します。- 各ブロック内の
tr(項目)をさらに走査し、thのテキスト(例: “title”)をキー、inputのvalue(例: “新しいお知らせ”)をバリューとするオブジェクト(matome)を作成します。 - それらのオブジェクトを配列(
exportDataArray)に格納します。 - 最後に
JSON.stringify()で配列全体をJSON文字列に変換し、隠しinput(#js-exportjson)にセットします。
- 各ブロック内の
このJavaScriptの処理により、ユーザーが並べ替えた通りの順番で、かつ編集・追加・削除した最新の状態がJSON文字列としてPHPに送信され、ファイルに保存されるわけです。
【重要】セキュリティに関する注意点
このコードは、簡易的にJSONを編集する機能を提供しますが、このままの状態で公開サーバーに設置するのは非常に危険です。
なぜなら、このページのURLを知っていれば誰でもアクセスし、データを編集・削除できてしまうからです。
必ず、以下のようなアクセス制限をサーバー側で設定してください。
- Basic認証(ID/パスワード認証)をかける。
- IPアドレス制限をかけ、特定の(オフィスの)IPアドレスからしかアクセスできないようにする。
あくまで「ソースコードを直接触るよりは安全」というレベルのツールであり、不特定多数のユーザーが使うためのものではないことを理解しておきましょう。
まとめ
今回は、PHPのfile_put_contentsとjQuery UIのsortableを組み合わせて、WebブラウザからJSONデータを編集できる簡易CMSの作り方を紹介しました。
WordPressを導入するほどではないけれど、クライアントや非エンジニアの担当者に安全に特定の情報(お知らせ、バナーリスト、営業時間など)を更新してもらいたい、というニーズは多く存在します。
この仕組みをベースに、CSSでデザインを整えたり、JSONの構造を変更して入力項目を自由にカスタマイズすることで、様々なプロジェクトに応用が可能です。
Webサイト運営の効率化に、ぜひ役立ててみてください。
よくある質問(FAQ)
Q1: JSONファイルがうまく読み込めません。または「データがありません」と表示されます。
A1: PHPファイル(index.phpなど)とJSONファイル(cmsTest.json)のパス(場所)が正しいか確認してください。コード内の$jsonUrl = "./cmsTest.json";という記述は、「PHPファイルと同じ階層にJSONファイルがある」ことを意味します。また、cmsTest.jsonファイルがサーバー上に存在し、中身が空でも[](空の配列)などの正しいJSON形式になっているか、ファイルのパーミッション(読み取り権限)が適切に設定されているかを確認してください。
Q2: このまま公開してもセキュリティは大丈夫ですか?
A2: いいえ、非常に危険です。本文中の「セキュリティに関する注意点」でも解説した通り、この管理ページにはアクセス制限がありません。必ずサーバー側でBasic認証(ID/パスワード)やIPアドレス制限を設定し、許可された関係者以外はアクセスできないようにしてください。
Q3: 編集したい項目(「title」など)を自由に変更・追加したいです。
A3: 対応可能です。まず、データの元となるcmsTest.jsonファイル内の構造を変更します(例:"title"の他に"date"や"link"を追加する)。
次に、PHPのechoJson()関数と、JavaScriptの$('#js-form-campaign').on('submit', ...)内の処理を、新しいJSON構造(追加したキー)に合わせて修正する必要があります。特にJavaScript側では、thのテキストをキーとして取得しているため、HTMLの構造とJSONのキーが一致するように注意深く調整してください。
