中級 PHP MySQL jQuery プラグイン

プレビュー付き画像フォームをデータベースに保存する(Upload Thumbs 版)

前のサンプル(画像付きフォームの保存・編集)と同じ仕組みを、画像プレビューを jQuery プラグイン「Upload Thumbs」に任せて作ります。プラグインを使うと JavaScript がどれだけ短くなるかを比べてみましょう。

このサンプルは2017〜2018年ごろに作成したものです。PHPのバージョンが上がり、そのままでは動かなくなっていたため、2026年に PHP 8.3 で動くように書き直し、解説も新しくしました。

DEMO 実際に動かしてみよう

追加画面 | 表示画面 | 編集画面

テキスト画像(1MBまで)


※ このデモのデータは、見に来たすべての人で共有されます。最新20件を超えると古いものから自動で削除されます。個人情報や人に見られて困る画像は送らないでください。

解説コードを読んでみよう

このサンプルでわかること

  • 自分で書いたプレビュー処理を、jQuery プラグイン(Upload Thumbs)に置き換える方法
  • あとから追加した入力欄にも、プラグインを設定し直す方法
  • 同じ仕組みを、設定(テーブル名や戻り先)だけ変えて使い回す考え方

このサンプルは、ひとつ前の「画像付きフォームをデータベースに保存・編集する」とサーバー側の仕組みがまったく同じです。画像のチェック・保存・縮小、データベースへの登録・更新・削除のくわしい説明は、そちらのページを先に読んでください。ここでは違うところだけを解説します。

使っているファイル

  • index.php / edit.php追加画面・編集画面(プレビューをプラグインで表示)
  • ../js/jquery.upload_thumbs.js画像プレビューのプラグイン Upload Thumbs
  • upload.php / update.php / view.php / del_*.php前のサンプルと同じ処理
  • common.php共通の設定と関数(使うテーブルが sp_img_02 になっている)

前のサンプルとの違い

前のサンプルこのサンプル
画像のプレビューFileReader を使って自分で書く(約10行)プラグインを呼ぶだけ(1行)
使うテーブルsp_img_01sp_img_02
編集して保存したあと表示画面へ移動編集画面に戻る(続けて編集できる)

1. プラグインを読み込む

プラグインは jQuery 本体のあとに読み込みます。このサイトでは jQuery は共通のヘッダーで読み込み済みなので、ページの <head> にプラグインを1行足すだけです。

index.php(7〜10行目) PHP
    <title><?= h(page_title($title ?? '')) ?></title>

    <!-- 画像プレビューのプラグイン(jQuery の後に読み込む) -->
    <script src="../js/jquery.upload_thumbs.js"></script>

2. ファイル選択欄にプラグインを設定する

$('input[type=file]').uploadThumbs({ ... }) と書くと、その入力欄で画像を選んだときに、自動でサムネイルが表示されます。

index.php(49〜70行目) JavaScript
<script>
$(function () {
    var MAX_ROWS = 5;  // 一度に送信できる行数

    // プレビューはプラグインにおまかせ。1行目の入力欄に設定する
    $('input[type=file]').uploadThumbs({ position: 0, imgbreak: true });

    // 「行を追加」ボタン
    $('#add').on('click', function () {
        if ($('.rows tbody tr').length >= MAX_ROWS) {
            $('#message').text('※ 一度に追加できるのは' + MAX_ROWS + '行までです。');
            return;
        }
        var row = '<tr>' +
            '<td><input type="text" name="text[]" maxlength="100"></td>' +
            '<td><input type="file" name="img[]" accept="image/*"></td>' +
            '</tr>';
        var $row = $(row).appendTo('.rows tbody');
        // 追加した行の入力欄にもプラグインを設定する
        $row.find('input[type=file]').uploadThumbs({ position: 0, imgbreak: true });
    });
});
オプション意味
position: 0サムネイルを入力欄の前に表示する(1 なら後ろ)
imgbreak: trueサムネイルのあとで改行する

プラグインは、実行した時点でページにある要素にしか設定されません。「行を追加」ボタンで新しく作った入力欄は、そのままではプレビューが出ません。そこで、行を追加するたびに $row.find('input[type=file]').uploadThumbs(...) で、新しい入力欄にも設定し直しています(66〜68行目)。

前のサンプルでは $(document).on('change', ...)(イベントの委譲)を使っていたので、この「設定し直し」は不要でした。自分で書くか、プラグインを使うかで、気をつける点が変わることがわかります。

3. 編集画面も同じ考え方

編集画面でも、最初にある入力欄にまとめて設定し、追加した行にはその都度設定します。

edit.php(75〜76行目) JavaScript
    // 画像のプレビューはプラグインにおまかせ
    $('input[type=file]').uploadThumbs({ position: 0, imgbreak: true });
edit.php(98〜112行目) JavaScript
    // 行を追加。新しい行の ID は空にしておく(update.php で「新規」と判断するため)
    $('#add').on('click', function () {
        if (added >= MAX_NEW) {
            $('#message').text('※ 一度に追加できるのは' + MAX_NEW + '行までです。');
            return;
        }
        added++;
        var row = '<tr>' +
            '<td><input type="text" name="text[]" maxlength="100"><input type="hidden" name="ID[]" value=""></td>' +
            '<td><input type="file" name="img[]" accept="image/*"></td>' +
            '<td><button type="button" class="del-line">行を削除</button></td>' +
            '</tr>';
        var $row = $(row).appendTo('.rows tbody');
        $row.find('input[type=file]').uploadThumbs({ position: 0, imgbreak: true });
    });

4. 設定を変えて使い回す(common.php)

サーバー側のファイルは前のサンプルと同じ内容で、違うのは common.php のテーブル名と、update.php の戻り先だけです。テーブル名を定数 TABLE にまとめておいたので、1か所を書き換えるだけで別のテーブルを使えます。

common.php(9〜16行目) PHP
// ---- 設定 ----------------------------------------------------
const TABLE           = 'sp_img_02';  // 使うテーブル
const USER_ID         = 1;            // サンプルなので、ユーザーと記事は固定
const POST_ID         = 1;
const MAX_ROWS        = 5;            // 1回に送信できる行数
const MAX_SIZE        = 1048576;      // 画像1枚の上限(1MB)
const MIDDLE_WIDTH    = 200;          // 中サイズ画像の横幅(px)
const THUMBNAIL_WIDTH = 100;          // サムネイルの横幅(px)
update.php(80〜85行目) PHP
} catch (Throwable $e) {
    show_error_page(['更新中にエラーが発生しました。時間をおいて、もう一度お試しください。'], 'edit.php');
}

header('Location: edit.php');  // 続けて編集できるように編集画面へ戻る
exit;

使うテーブルは、前のサンプルとテーブル名が違うだけで、列の構成は同じです。

テーブルの作成 SQL
CREATE TABLE sp_img_02 (
  ID      INT AUTO_INCREMENT PRIMARY KEY,
  user_id INT NOT NULL,
  post_id INT NOT NULL,
  text    VARCHAR(255) NOT NULL DEFAULT '',
  img     VARCHAR(255) NOT NULL DEFAULT '',
  date    DATETIME DEFAULT CURRENT_TIMESTAMP
) DEFAULT CHARSET=utf8mb4;

PHP 8.3 で書き直したポイント

  • 前のサンプルと同じく、定数名の誤字(MIDEEL_WIDTH)、PDO の例外、count() の扱いなど、PHP 8 で止まっていた箇所を直しました。
  • 旧版の「全て削除」は、表示に使うテーブル(sp_img_02)とは別のテーブル(img_02)を削除していたため、押してもデータが消えませんでした。同じ TABLE 定数を使うことで、こうした食い違いが起きないようにしています。
  • 画像や行を削除するときは、ブラウザからファイルの場所を受け取らず、行の ID だけを受け取るようにしました。

オプションを position: 1 に変えて、サムネイルの表示位置がどう変わるか試してみましょう。

↑