2026年5月20日
2026年5月20日
WordPressプラグインでカスタムデータベーステーブルを作成する方法
はじめに
WordPressプラグインで独自のデータを管理する場合、カスタムデータベーステーブルが必要になることがあります。dbDelta() を使ったテーブル作成と、$wpdb を使ったデータ操作の方法を解説します。
症状・原因
- プラグインで管理する独自データをDBに保存したい
- wp_postmetaやwp_optionsに収まらない複雑なデータ構造が必要
- プラグインのアクティベート時にテーブルを自動作成したい
- テーブルのスキーマをバージョンアップ時に安全に変更したい
解決手順
ステップ1:アクティベート時にテーブルを作成する
// プラグインファイル
register_activation_hook(__FILE__, 'myplugin_create_tables');
function myplugin_create_tables(): void {
global $wpdb;
$charset_collate = $wpdb->get_charset_collate();
$table_name = $wpdb->prefix . 'my_logs';
$sql = "CREATE TABLE {$table_name} (
id BIGINT(20) UNSIGNED NOT NULL AUTO_INCREMENT,
user_id BIGINT(20) UNSIGNED NOT NULL DEFAULT 0,
action VARCHAR(100) NOT NULL DEFAULT '',
description TEXT NOT NULL,
created_at DATETIME NOT NULL DEFAULT CURRENT_TIMESTAMP,
PRIMARY KEY (id),
KEY user_id (user_id),
KEY created_at (created_at)
) {$charset_collate};";
require_once ABSPATH . 'wp-admin/includes/upgrade.php';
dbDelta($sql); // 新規作成 or 差分のみ変更(安全)
// テーブルバージョンを保存
update_option('myplugin_db_version', '1.0');
}
ステップ2:テーブルバージョンで安全にアップグレードする
// プラグイン読み込み時にバージョンをチェック
add_action('plugins_loaded', function(): void {
$current = get_option('myplugin_db_version', '0');
if (version_compare($current, '1.1', '<')) {
myplugin_upgrade_db_v1_1();
}
});
function myplugin_upgrade_db_v1_1(): void {
global $wpdb;
$table = $wpdb->prefix . 'my_logs';
// カラムを追加(dbDeltaで差分のみ適用)
$sql = "CREATE TABLE {$table} (
id BIGINT(20) UNSIGNED NOT NULL AUTO_INCREMENT,
user_id BIGINT(20) UNSIGNED NOT NULL DEFAULT 0,
action VARCHAR(100) NOT NULL DEFAULT '',
description TEXT NOT NULL,
ip_address VARCHAR(45) NOT NULL DEFAULT '',
created_at DATETIME NOT NULL DEFAULT CURRENT_TIMESTAMP,
PRIMARY KEY (id),
KEY user_id (user_id)
) " . $wpdb->get_charset_collate() . ";";
require_once ABSPATH . 'wp-admin/includes/upgrade.php';
dbDelta($sql);
update_option('myplugin_db_version', '1.1');
}
ステップ3:$wpdbでCRUD操作を行う
global $wpdb;
$table = $wpdb->prefix . 'my_logs';
// INSERT(プレースホルダーで安全に)
$wpdb->insert($table, [
'user_id' => get_current_user_id(),
'action' => 'login',
'description' => 'ユーザーがログインしました',
'ip_address' => sanitize_text_field($_SERVER['REMOTE_ADDR'] ?? ''),
], ['%d', '%s', '%s', '%s']);
$inserted_id = $wpdb->insert_id;
// SELECT(prepare でSQLインジェクション対策)
$logs = $wpdb->get_results(
$wpdb->prepare(
"SELECT * FROM {$table} WHERE user_id = %d ORDER BY created_at DESC LIMIT %d",
get_current_user_id(),
10
)
);
// UPDATE
$wpdb->update(
$table,
['description' => '更新済み'], // 更新するデータ
['id' => 42], // WHERE条件
['%s'], // データのフォーマット
['%d'] // WHERE のフォーマット
);
// DELETE
$wpdb->delete($table, ['id' => 42], ['%d']);
ステップ4:アンインストール時にテーブルを削除する
// uninstall.php(プラグインディレクトリに配置)
if (!defined('WP_UNINSTALL_PLUGIN')) {
exit;
}
global $wpdb;
$table = $wpdb->prefix . 'my_logs';
// phpcs:ignore WordPress.DB.PreparedSQL.InterpolatedNotPrepared
$wpdb->query("DROP TABLE IF EXISTS {$table}");
delete_option('myplugin_db_version');
ステップ5:WP-CLIでテーブルを確認する
# カスタムテーブルの存在確認
wp db query "SHOW TABLES LIKE 'wp_my_%'"
# テーブル構造を確認
wp db query "DESCRIBE wp_my_logs"
# データ件数を確認
wp db query "SELECT COUNT(*) FROM wp_my_logs"
# テーブルのサイズを確認
wp db query "SELECT table_name, ROUND(data_length/1024/1024, 2) AS 'MB'
FROM information_schema.tables
WHERE table_schema = DATABASE()
AND table_name LIKE 'wp_my_%'"
注意事項
dbDelta()は既存テーブルに対して列追加は安全ですが、列削除・型変更は行いません。削除が必要な場合はALTER TABLEを直接実行してください$wpdb->prepare()を使わずにSQLを組み立てるとSQLインジェクションの危険があります- マルチサイトでは
$wpdb->prefixがサイトごとに異なります。グローバルテーブルには$wpdb->base_prefixを使ってください
まとめ
プラグインのアクティベート時に dbDelta() でカスタムテーブルを作成し、バージョン管理でスキーマを安全にアップグレードします。CRUD操作は必ず $wpdb->prepare() でサニタイズし、アンインストール時は uninstall.php でテーブルを削除します。