解説コードを読んでみよう
このサンプルでわかること
- 自分で書いたプレビュー処理を、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_01 | sp_img_02 |
| 編集して保存したあと | 表示画面へ移動 | 編集画面に戻る(続けて編集できる) |
1. プラグインを読み込む
プラグインは jQuery 本体のあとに読み込みます。このサイトでは jQuery は共通のヘッダーで読み込み済みなので、ページの <head> にプラグインを1行足すだけです。
<title><?= h(page_title($title ?? '')) ?></title>
<!-- 画像プレビューのプラグイン(jQuery の後に読み込む) -->
<script src="../js/jquery.upload_thumbs.js"></script>
2. ファイル選択欄にプラグインを設定する
$('input[type=file]').uploadThumbs({ ... }) と書くと、その入力欄で画像を選んだときに、自動でサムネイルが表示されます。
<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. 編集画面も同じ考え方
編集画面でも、最初にある入力欄にまとめて設定し、追加した行にはその都度設定します。
// 画像のプレビューはプラグインにおまかせ
$('input[type=file]').uploadThumbs({ position: 0, imgbreak: true });
// 行を追加。新しい行の 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か所を書き換えるだけで別のテーブルを使えます。
// ---- 設定 ----------------------------------------------------
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)
} catch (Throwable $e) {
show_error_page(['更新中にエラーが発生しました。時間をおいて、もう一度お試しください。'], 'edit.php');
}
header('Location: edit.php'); // 続けて編集できるように編集画面へ戻る
exit;
使うテーブルは、前のサンプルとテーブル名が違うだけで、列の構成は同じです。
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 に変えて、サムネイルの表示位置がどう変わるか試してみましょう。