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 でテーブルを削除します。

お気軽にご相談ください

お見積りへ お問い合わせへ