PHPとjQueryで実現!ドラッグ&ドロップでJSONを編集できる簡易CMSの作り方

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>

ポイント解説:

  1. 新規作成: 既存のブロックをcloneNode(true)で複製し、中身を空にしてから先頭に追加しています。
  2. 削除: $(this).parents('.block-article').remove()で、押されたボタンの親であるブロックごとDOMから削除します。
  3. 並べ替え: jQuery UIのsortable()メソッドを呼び出すだけで、id="sortable"の範囲がドラッグ&ドロップ可能になります。
  4. 更新(JSON生成): これが最も重要です。フォーム送信時(on('submit'))、画面に表示されている全ての.tableCampaign(各ブロック)をeachで走査します。
    • 各ブロック内のtr(項目)をさらに走査し、thのテキスト(例: “title”)をキー、inputvalue(例: “新しいお知らせ”)をバリューとするオブジェクト(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のキーが一致するように注意深く調整してください。

CONTACT

webサイト制作、デザインに関するご相談、御見積のご依頼など、弊社へのお問い合わせはこちら