dbDelta()
dbDelta()関数は、SQLのCREATE TABLE文を元に、テーブルの新規作成や既存テーブルの構造更新(ALTER)を自動で行う強力な関数です。データや既存のカラムを維持しながら、プラグインのバージョンアップ等に合わせてデータベース構造を最新に保つ効果があります。
主な効果と特徴:
- 安全な構造更新: テーブルが存在しない場合は作成し、存在する場合は
ALTER TABLEを発行して差分を更新する。 - バージョン対応: プラグイン有効化時やアップグレード時にスキーマを自動更新できる。
- 制約: カラム定義は1行に1つずつ記述し、
PRIMARY KEYの前後にはスペースが2つ必要など、厳密な書式が求められる。
使用する際は、require_once( ABSPATH . 'wp-admin/includes/upgrade.php' );で関数を読み込む必要があります。
⚠️注意
テーブル追加、変更した場合は一度:
- プラグイン停止
- プラグイン削除しないでOK
- 再度有効化
してください。
そうすると新テーブルが作られます。
テーブルの正しい書き方
dbDelta() は WordPressでカスタムテーブルを安全に作るための公式関数 ですが、書き方に超クセがあります。ここを外すと動きません。
動いても不安定でバグりやすい
✅ 基本の正しい書き方(完全テンプレ)
- 改行: 各カラムの定義は、必ず独立した1行にする。
- スペース:
PRIMARY KEYなどの定義の前後には2つのスペースを入れる。 - インデックス:
KEYキーワードを使用する(INDEXは使用しない)。 - インデックス名:
KEYの次はスペースを1つ空け、その後にインデックス名、スペース、括弧でカラム名を書く。 - クォーテーション: カラム名やテーブル名にバッククォート(
)や引用符(')を使用しない。 - データ型: すべて小文字にする(
VARCHARではなくvarchar)。 - ID定義:
id bigint(20) NOT NULL AUTO_INCREMENTのように、必ず長さを明記する
|
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 |
function myplugin_create_table() { global $wpdb; $table_name = $wpdb->prefix . 'myplugin_data'; $charset_collate = $wpdb->get_charset_collate(); $sql = "CREATE TABLE $table_name ( id bigint(20) unsigned NOT NULL AUTO_INCREMENT, user_id bigint(20) unsigned NOT NULL, score int(11) NOT NULL DEFAULT 0, created_at datetime NOT NULL DEFAULT CURRENT_TIMESTAMP, PRIMARY KEY (id), KEY user_id (user_id) ) $charset_collate;"; require_once ABSPATH . 'wp-admin/includes/upgrade.php'; dbDelta($sql); } |
🔥 超重要ルール(これ守らないと壊れます)
① require_once upgrade.php は必須
|
1 |
require_once ABSPATH . 'wp-admin/includes/upgrade.php'; |
これを忘れると dbDelta() は使えません。
② SQLの書式は厳密
❌ ダメ例
- フィールド定義の最後にカンマ
PRIMARY KEY(id)← スペースなし- インデックスに
INDEXを使う IF NOT EXISTSを付ける
✅ 正しい書き方
- PRIMARY KEY の後に スペース2つ
|
1 |
PRIMARY KEY (id) |
インデックスは KEY
|
1 |
KEY user_id (user_id) |
IF NOT EXISTS は 絶対に書かない
🧠 dbDelta()の特徴
| 機能 | 対応 |
|---|---|
| テーブル作成 | ✅ |
| カラム追加 | ✅ |
| インデックス追加 | ✅ |
| カラム削除 | ❌ |
| カラム型変更 | △(うまくいかないこと多い) |
🚀 プラグイン有効化時に実行する例
|
1 |
register_activation_hook(__FILE__, 'myplugin_create_table'); |
🔐 バージョン管理するのが正解
実務ではこうします:
|
1 2 3 4 5 6 |
function myplugin_install() { myplugin_create_table(); add_option('myplugin_db_version', '1.0'); } register_activation_hook(__FILE__, 'myplugin_install'); |
将来カラム追加するとき:
|
1 2 3 4 5 6 7 8 9 |
function myplugin_update_db() { $installed_ver = get_option('myplugin_db_version'); if ($installed_ver != '1.1') { myplugin_create_table(); update_option('myplugin_db_version', '1.1'); } } add_action('plugins_loaded', 'myplugin_update_db'); |
🎯 よくあるバグ
- SQLの改行コードが変
ENGINE=InnoDBを直接書いている- 文字コードを指定していない
- PRIMARY KEYのスペースが1個
データ型&属性
1. よく使われるデータ型 (Column Types)
数値、文字列、日付など、WordPressのテーブル作成で一般的に使われる型です。
- 整数型 (Integer)
- 文字列型 (String)
- 日付・時間型 (Date/Time)
- 数値型 (Number)
2. カラムの設定・制約 (Constraints)
カラムの属性を設定する記述です
NOT NULL: 空の値(NULL)を許可しないNULL: 空の値(NULL)を許可する(デフォルト)AUTO_INCREMENT: IDなど、自動で連番を振るDEFAULT 'value': デフォルト値を設定DEFAULT NULL: デフォルト値をNULLに設定PRIMARY KEY (column_name): 主キーの設定KEY index_name (column_name): 通常インデックスの設定(INDEXではなくKEYを使用)UNIQUE KEY index_name (column_name): ユニークインデックスの設定CHARACTER SET charset_name / COLLATE collation_name: 文字コード・照合順序
phpMyAdmin
その他関数
データベースのカラムには変数が使えるので決まったものが入るのであれば配列でマップしておくと楽
|
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 |
<?php $hand_to_col = [ 'rock' => 'rock_count', 'scissors' => 'scissors_count', 'paper' => 'paper_count', ]; if (isset($hand_to_col[$attack_hand])) { $col = $hand_to_col[$attack_hand]; $wpdb->query( $wpdb->prepare( "UPDATE {$users} SET {$col} = {$col} + 1 WHERE user_id_str = %s", $attacker_id ) ); } |
$wpdb->get_charset_collate()
データベーステーブルを作成または更新する際に、WordPress環境(wp-config.phpで設定された文字セットと照合順序)と一致する文字セット(Character Set)と照合順序(Collation)を取得するためのメソッドです。
使用例
通常、dbDelta() 関数と一緒に使用します。
|
1 2 3 4 5 6 7 8 9 10 11 12 13 |
global $wpdb; $table_name = $wpdb->prefix . 'my_table'; // 文字セットと照合順序を取得 $charset_collate = $wpdb->get_charset_collate(); $sql = "CREATE TABLE $table_name ( id mediumint(9) NOT NULL AUTO_INCREMENT, data varchar(255) NOT NULL, PRIMARY KEY (id) ) $charset_collate;"; // ここで適用 require_once( ABSPATH . 'wp-admin/includes/upgrade.php' ); dbDelta( $sql ); |
戻り値の例
通常、DEFAULT CHARACTER SET utf8mb4 COLLATE utf8mb4_unicode_ci のような文字列が返されます。
まとめ
プラグインやテーマ開発で独自のテーブル(CREATE TABLE)を作成する際は、必ずこの関数を使って文字セットを設定すべきです。特に多言語サイトや、日本語を扱う場合に重要です。
$wpdb->get_results()
類似関数、比較表
| 関数名 | 取得データ | 戻り値の形式 | 主な用途 |
|---|---|---|---|
| get_var | 1列 × 1行 | 単一の値 (string/int) | 合計値、個数、特定の1フィールド |
| get_row | 複数列 × 1行 | オブジェクト/配列 | 特定の1レコード詳細 |
| get_results | 複数列 × 複数行 | オブジェクト/配列の配列 | 一覧表示、ループ処理 |
データベースから複数行のデータを取得する際に使用されます。
1. 第一引数:$query(文字列 / 必須)
実行したい SQL文(SELECTクエリ) を指定します。
セキュリティ(SQLインジェクション対策)のため、外部からの入力値を含む場合は必ず $wpdb->prepare() でラップしたクエリを渡すのが推奨されます。
2. 第二引数:$output_type(定数 / 任意)
返り値の データ形式 を指定します。デフォルトは OBJECT です。
| 指定できる定数 | 説明 | データの取り出し方 |
|---|---|---|
OBJECT (初期値) | 数値添字配列の中に、各行がオブジェクトとして格納される | $results[0]->column_name |
ARRAY_A | 数値添字配列の中に、各行が連想配列(カラム名がキー)として格納される | $results[0]['column_name'] |
ARRAY_N | 数値添字配列の中に、各行が数値添字配列として格納される | $results[0][0] |
OBJECT_K | 第一カラムの値をキーとした、行オブジェクトの連想配列を返す | $results['key_value']->column_name |
基本的な使い方の例
|
1 2 3 4 5 6 7 8 9 10 11 12 |
global $wpdb; // 1. クエリを準備 $query = $wpdb->prepare("SELECT * FROM {$wpdb->posts} WHERE post_status = %s", 'publish'); // 2. 連想配列形式で取得 $results = $wpdb->get_results($query, ARRAY_A); // 3. 結果の表示 foreach ($results as $row) { echo $row['post_title']; } |
$wpdb->prepare()
SQL文の中に変数を安全に埋め込むためのメソッドです。主な引数は、「SQLの雛形(クエリ)」と「埋め込む値」の2つ(またはそれ以上)です。
1. 第一引数:$query(文字列)
埋め込みたい場所に 「プレースホルダ」 と呼ばれる記号を置いたSQL文を指定します。
よく使われるプレースホルダ:
%d:整数(integer)%s:文字列(string)%f:浮動小数点数(float)%i:テーブル名やカラム名(identifier) ※WP 6.1以降
2. 第二引数以降(または配列):$args
プレースホルダに当てはめる 「実際の値」 を指定します。
- 個別指定(可変長引数):
$wpdb->prepare($sql, $val1, $val2, ...)のように順に並べます。 - 配列指定:
$wpdb->prepare($sql, array($val1, $val2))のように、値をひとまとめにした配列を渡すことも可能です。
具体的な使用例
プレースホルダを使うことで、WordPress Developer Resources で解説されている通り、クォート処理(' で囲むなど)が自動で行われ、SQLインジェクションを防ぐことができます。
|
1 2 3 4 5 6 7 8 9 10 11 12 13 |
global $wpdb; $user_id = 5; $status = 'active'; // %d は整数、%s は文字列に置き換わります $query = $wpdb->prepare( "SELECT * FROM {$wpdb->prefix}users WHERE ID = %d AND user_status = %s", $user_id, // %d に入る $status // %s に入る ); $results = $wpdb->get_results($query); |
注意点
- クォートは不要: プレースホルダ自体を
'(シングルクォート)で囲む必要はありません(例:WHERE name = %sでOK、'%s'とは書かない)。 %記号の扱い:LIKE検索などで%を文字として使いたい場合は、%%と重ねて記述するか、WordPressの公式ガイド にあるように値を渡す側で調整します。
データベースの注意点とメモ
user_id のようなカラム名は【insert()】等で %s で明示しないと数値扱いされて文字列を入れたときに 0 になる。
|
1 2 3 4 5 6 7 8 9 10 11 |
$wpdb->insert( $table, [ "user_id" => $user_id, "display_name" => $display_name ], [ "%s", "%s" ] ); |
| AUTO_INCREMENT | 新しいレコード挿入時に自動的に連番が付く |
| UNSIGNED | 符号なし(0以上の正の数のみ)→ 0 ~ 18,446,744,073,709,551,615 |
| BIGINT(20) | 64ビット整数型(-9,223,372,036,854,775,808 ~ 9,223,372,036,854,775,807) |
| TEXT | 約65,535文字(65KB) |
| MEDIUMTEXT | 約1,600万文字(16MB) |
| LONGTEXT | 約42億文字(4GB) |
PHPでダブルクォーテーション内では生の変数名では動かない時がある、その時は テーブルカラム名 = %s を使うか変数名を '{}' で囲むと動く。
データベースのカラム名に寄ってはWordPressが型を勝手に解釈してしまい入らない時がある。
ランキングテーブルから順位を取得する
|
1 2 3 4 5 6 7 8 9 10 |
$rank = $wpdb->get_var( $wpdb->prepare( "SELECT COUNT(*) + 1 FROM $table WHERE year_month = %s AND score > %d", $year_month, $new_score ) ); |
これで
「自分より上の人数 + 1」=順位
WordPressのデータベーステーブル
1. wp_posts (投稿、ページ、添付ファイル)
WordPressで最も重要なテーブルです。投稿データそのものを保存します。
- ID (bigint(20)): ユニークな投稿ID
- post_author (bigint(20)): 投稿者のユーザーID
- post_date (datetime): 投稿日時
- post_content (longtext): 記事の本文
- post_title (text): 記事のタイトル
- post_status (varchar(20)): 状態(publish:公開, draft:下書き)
- post_name (varchar(200)): スラッグ(URLの一部)
- post_type (varchar(20)): 投稿タイプ(post, page, attachment, nav_menu_itemなど)
- post_mime_type (varchar(100)): ファイルのMIMEタイプ(画像や添付ファイルの場合)
2. wp_postmeta (投稿メタデータ)
投稿に付随する追加情報(カスタムフィールド、ACFのデータなど)を保存します。
- meta_id (bigint(20)): メタデータID
- post_id (bigint(20)): 対応する
wp_postsのID - meta_key (varchar(255)): メタデータ名(例:
_edit_lock_wp_page_template) - meta_value (longtext): メタデータの値
3. wp_users (ユーザー情報)
ユーザーの認証情報など基本情報を保存します
- ID (bigint(20)): ユーザーID
- user_login (varchar(60)): ログインID(ユーザー名)
- user_pass (varchar(255)): ハッシュ化されたパスワード
- user_nicename (varchar(50)): URL用ユーザー名
- user_email (varchar(100)): メールアドレス
- user_registered (datetime): 登録日時
4. wp_usermeta (ユーザーメタデータ)
ユーザーの権限やプロフィールなどの詳細情報を保存します。
- umeta_id (bigint(20)): メタデータID
- user_id (bigint(20)): 対応する
wp_usersのID - meta_key (varchar(255)): メタデータ名(例:
wp_capabilitiesnickname) - meta_value (longtext): メタデータの値
5. wp_options (サイト設定)
テーマ、プラグイン、WordPress一般の設定情報を保存します。
- option_id (bigint(20)): 設定ID
- option_name (varchar(191)): 設定項目名(例:
siteurl`blogname) - option_value (longtext): 設定値
- autoload (varchar(20)): 読み込み設定(yes/no)
6. wp_terms (カテゴリー/タグの名前)
カテゴリーやタグの名前とスラッグを保存します
- term_id (bigint(20)): 用語ID
- name (varchar(200)): 名前
- slug (varchar(200)): スラッグ
- term_group (bigint(10)): グループID
7. wp_term_taxonomy (分類の定義)
wp_terms のデータがカテゴリーか、タグか、あるいは他のタクソノミー(分類)かを定義します
- term_taxonomy_id (bigint(20)): 分類ID
- term_id (bigint(20)):
wp_termsのID - taxonomy (varchar(32)): 分類の種類(category, post_tag, nav_menu)
- description (longtext): 分類の説明
- count (bigint(20)): 関連付けられた投稿数
8. wp_term_relationships (記事と分類の紐付け)
投稿IDと分類ID(term_taxonomy_id)を紐付けます
- object_id (bigint(20)): 投稿ID
- term_taxonomy_id (bigint(20)):
wp_term_taxonomyのID - term_order (int(11)): 順序
9. wp_comments (コメント)
コメントのデータを保存します
- comment_ID (bigint(20)): コメントID
- comment_post_ID (bigint(20)): コメントされた投稿ID
- comment_author (tinytext): コメント投稿者名
- comment_content (text): コメント内容
- comment_approved (varchar(20)): 承認状態
10. wp_commentmeta (コメントメタデータ)
コメントに付随する追加情報を保存します
- meta_id (bigint(20)): メタデータID
- comment_id (bigint(20)):
wp_commentsのID - meta_key (varchar(255)): メタデータ名
- meta_value (longtext): メタデータの値
11. wp_termmeta (タームのメタデータ)
カテゴリーやタグにメタデータを保存します(比較的新しく追加)
12. wp_links (リンク – 非推奨)
ブログロールなどのリンクを保存。現在はほぼ使用されていない。
値の存在確認
get_var() でカウントする方法 (推奨)
該当するデータがあるかどうかの判定に最もよく使われます。1件でも見つかれば存在するとみなします。
|
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 |
global $wpdb; // 調査したい値とテーブル・カラム名 $search_value = 'target_value'; $table_name = $wpdb->prefix . 'table_name'; // テーブル名に接頭辞をつける // カウントを取得してチェック $count = $wpdb->get_var( $wpdb->prepare( "SELECT COUNT(*) FROM $table_name WHERE column_name = %s", $search_value ) ); if ( $count > 0 ) { echo '値は存在します。'; } else { echo '値は存在しません。'; } |
EXISTS を使う方法
データベースのレコード数が多い場合、COUNT(*) より EXISTS の方が高速に動作する場合があります
|
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 |
global $wpdb; $search_value = 'target_value'; $table_name = $wpdb->prefix . 'table_name'; // EXISTS クエリ $exists = $wpdb->get_var( $wpdb->prepare( "SELECT EXISTS(SELECT 1 FROM $table_name WHERE column_name = %s LIMIT 1)", $search_value ) ); if ( $exists ) { echo '値は存在します。'; } else { echo '値は存在しません。'; } |
テーブル/カラムの存在確認 (メタデータ用)
テーブルや特定のカラムが存在するか自体をチェックしたい場合は、SQLで information_schema を照会するか、WordPressの dbDelta を使用します。
|
1 2 3 4 5 6 7 |
global $wpdb; $table_name = $wpdb->prefix . 'table_name'; // テーブルが存在するか確認 if ( $wpdb->get_var( "SHOW TABLES LIKE '$table_name'" ) === $table_name ) { // テーブルが存在する場合の処理 } |
注意点
- 必ず
$wpdb->prepareを使用してください。 SQLインジェクション攻撃を防ぐために必須です。 $wpdb->prefixを使用して、カスタムテーブルでも安全に接頭辞(wp_)に対応させます
コメント