ワードプレスにおいて、DBデータの取得・登録といった基本操作方法をまとめます。
wpdbクラスはワードプレスで用意されているクラスであり、ここにDB操作に必要な関数が定義されています。
codexをみても関数の種類が多く、"自分がどの関数を使えばよいかパッと見で判断できない"ということが多いため、早見表を作りました。
wpdbクラスの概要
詳細な内容は、codexのwpdbに関するページにて確認できます。
インスタンスの扱い方
接続したいDBによって、インスタンスの扱い方は以下となります。
ワードプレスで利用しているデータベースと接続したい場合
グローバル変数「$wpdb」にて、インスタンスを管理しています。
これは、ワードプレス側で管理しているため、開発者はインスタンス生成する必要がなく、単純に$wpdbにて関数呼び出しを行うことでDB操作が可能です。
以下、サンプルです。
get_results( 'SELECT * FROM wp_options WHERE option_id = 1', OBJECT );
?>
上記のように、グローバル変数$wpdbを利用するためには、各テンプレートファイルにて『global $wpdb;』を宣言することで利用可能となります。
ワードプレスで利用していないデータベースと接続したい場合
必要なデータベース接続情報を設定の上で、インスタンスを新しく生成する必要があります。
基本的に、他システムのDBを直接参照するようなマネはしない方がよろしいので、今回はサンプルコードを割愛します。(というか調べてません。)
SQLのエスケープ[prepare()]
SQLインジェクション対策のために、wpdbクラスではprepare()メソッドが用意されています。
escape()メソッドやescape_by_ref()メソッドも用意されていますが、ver5.0.3時点では非推奨です。
特別な理由がなければprepare()メソッドを用いましょう。
引数
- 第1引数:実行対象のSQL文
 - 第2引数以降:SQLのプレースフォルダに代入する値。オプション指定のため存在しない場合は未指定でOK。
 
戻り値
エスケープされたSQL文。
サンプル
以下のサンプルでは、foo=の部分に$name変数の値を、status=の部分に$status変数の値をそれぞれ代入した上で、SQL文を無害化しています。
prepare(
    "SELECT something FROM table WHERE foo = %s and status = %d",
    $name, // 未エスケープの文字列 (関数が無害化します)
    $status // 信頼できない整数値 (関数が無害化します)
    );
?>
より詳しく知りたい場合は、codexのデータ検証に関するページを参照してください。
任意のSQLを実行する関数[query()]
任意のSQLを実行するためには、query()メソッドを利用します。
引数として、prepare()メソッドの返り値を渡してあげます。
引数
- 第1引数:実行対象のSQL文
 
戻り値
- SQLの実行に成功した場合:True
 - SQLの実行に失敗した場合:False
 
サンプル
query( $wpdb->prepare( 
	"
		INSERT INTO $wpdb->postmeta
		( post_id, meta_key, meta_value )
		VALUES ( %d, %s, %s )
	", 
        10, 
	$metakey, 
	$metavalue 
) );
?>
wpdbクラスを用いたデータ操作
複数行×複数列のデータ抽出(select)[get_result()]
一般的なselect文を発行して結果を得たい場合はget_results()メソッドを利用します。
引数
- 第1引数:実行対象のselect文
 - 第2引数:戻り値の型としてOBJECT、OBJECT_K、ARRAY_A、ARRAY_Nのどれかを指定
 
戻り値
第2引数で指定した型のデータが返却されます。詳細はサンプル部分をご確認ください。
- OBJECT:行レコードをオブジェクト化したもののインデックス配列
 - OBJECT_K:行レコードをオブジェクト化したものの連想配列(キーは第1カラムの値)
 - ARRAY_A:行レコードを連想配列化したもののインデックス配列
 - ARRAY_N:行レコードをインデックス配列化したもののインデックス配列
 
サンプル
第2引数で「OBJECT」を指定した場合。
get_results( 
	"
	SELECT ID, post_title 
	FROM $wpdb->posts
	WHERE post_status = 'draft' 
		AND post_author = 5
	"
    ); // 第2引数を指定しない場合はデフォルトの"OBJECT"となる
    // オブジェクトがインデックス配列で返却されるため、カラム値を取得しようとすると以下のような記述となる。
    foreach($rows as $row) {
      $id = $row->ID; 
    }
?>
第2引数で「OBJECT_K」を指定した場合。
get_results( 
	"
	SELECT ID, post_title 
	FROM $wpdb->posts
	WHERE post_status = 'draft' 
		AND post_author = 5
	","OBJECT_K"
    ); 
    // オブジェクトの連想配列で返却されるため、カラム値を取得しようとすると以下のような記述となる。
    foreach($rows as $row) {
      $id = $row->ID; 
    }
    // 例えば、IDが第1カラムで、かつID=2のレコード情報を取得したい場合は以下の通り。
    $title = $rows[2]->TITLE;
?>
第2引数で「ARRAY_A」を指定した場合。
get_results( 
	"
	SELECT ID, post_title 
	FROM $wpdb->posts
	WHERE post_status = 'draft' 
		AND post_author = 5
	","ARRAY_A"
    ); 
    //連想配列のインデックス配列で返却されるため、カラム値を取得しようとすると以下のような記述となる。
    foreach($rows as $row) {
      $id = $row['ID']; 
    }
?>
第2引数で「ARRAY_N」を指定した場合。
get_results( 
	"
	SELECT ID, post_title 
	FROM $wpdb->posts
	WHERE post_status = 'draft' 
		AND post_author = 5
	","ARRAY_N"
    ); 
    // インデックス配列のインデックス配列で返却されるため、カラム値を取得しようとすると以下のような記述となる。
    // 例えば、IDが1カラム目の場合は以下の通り。
    foreach($rows as $row) {
      $id = $row[0]; // 0は1カラム目を表す。2カラム目の場合は1を指定する。
    }
?>
単一列のデータ抽出(select)[get_col()]
引数
- 第1引数:実行対象のselect文
 - 第2引数:取得対象の列番号(1列目を指定する時は0を指定)
 
第2引数は、複数列取得される場合に、何列目を取得対象とするか?を指定できます。
戻り値
取得した列の配列
サンプル
<?php
  $col_list = $wpdb->get_col( "SELECT * FROM $wpdb->users", 4 );
  foreach ( $col_list as $elem ) {
    echo $elem;
  }
?>
単一行のデータ抽出(select)[get_row()]
引数
- 第1引数:実行対象のselect文
 - 第2引数:戻り値の型としてOBJECT、ARRAY_A、ARRAY_Nのどれかを指定
 - 第3引数:取得対象の行番号
 
戻り値
取得した行情報。第2引数で指定した型のデータで返却される。
- OBJECT:行レコードをオブジェクト化したもののインデックス配列
 - ARRAY_A:行レコードを連想配列化したもののインデックス配列
 - ARRAY_N:行レコードをインデックス配列化したもののインデックス配列
 
各型の扱い型については、get_result()のサンプル部分にまとめていますので、そちらをご参照ください。
サンプル
<?php $result_list = $wpdb->get_row( "SELECT * FROM $wpdb->users", ARRAY_A, 0 ); echo $result_list['user_name']; ?>
単一の値データ抽出(select)[get_var()]
引数
- 第1引数:実行対象のselect文
 - 第2引数:取得対象の列番号(1列目を指定する時は0を指定)
 - 第3引数:取得対象の行番号(1行目を指定する時は0を指定)
 
第2引数と第3引数は、select句で複数列×複数行の取得を指定した際に、何列目の何行目の値をget_var()での取得値とするかを指定することができます。
戻り値
取得できた単一の値。
サンプル
<?php
  $user_count = $wpdb->get_var( "SELECT COUNT(*) FROM $wpdb->users" );
  echo "<p>User count is {$user_count}</p>";
?>
データ登録(insert)[insert()]
insert文の実行を行いたい場合はinsert()メソッドを利用します。
引数
- 第1引数:対象テーブル
 - 第2引数:挿入データ(キー:カラム名、値:設定値の連想配列で設定)
 - 第3引数:データフォーマット(第2引数と対応させる形で配列で指定)(%s:文字列、%d:整数、%f:浮動小数点数のいずれかを指定)
 
戻り値
- 行を挿入できた場合:1(insertできた行数=常に1)
 - 行の挿入に失敗した場合:false
 
サンプル
insert( 
	'table', 
	array( 
		'column1' => 'value1', 
		'column2' => 123 
	), 
	array( 
		'%s', 
		'%d' 
	) 
);
?>
データ変更(update)[update()]
登録済みデータの変更については、update()とreplace()の2パターンありますが、replace()は使いにくそうなので、update()を使うこととします。
引き数
- 第1引数:対象テーブル
 - 第2引数:更新するデータ(キー:カラム名、値:設定値の連想配列で設定)
 - 第3引数:where句として使う名前付き配列(キー:カラム名、値:設定値の連想配列で設定)
 - 第4引数:データフォーマット(第2引数と対応させる形で配列で指定)(%s:文字列、%d:整数、%f:浮動小数点数のいずれかを指定)
 - 第5引数:データフォーマット(第3引数と対応させる形で配列で指定)(%s:文字列、%d:整数、%f:浮動小数点数のいずれかを指定)
 
戻り値
- 更新に成功した場合:1(更新されたレコード数=1)
 - 指定データと既存データが同一だった場合:0(更新されない=更新されたレコード数が0)
 - 更新に失敗した場合:false
 
サンプル
update( 
	'table', 
	array( 
		'column1' => 'value1',	// string
		'column2' => 'value2'	// integer (number) 
	), 
	array( 'ID' => 1 ), 
	array( 
		'%s',	// value1
		'%d'	// value2
	), 
	array( '%d' ) 
);
?>
データ削除(delete)[delete()]
delete文発行したい場合はdelete()メソッドを利用します。
引数
- 第1引数:テーブル名
 - 第2引数:where句として使う名前付き配列(キー:カラム名、値:設定値の連想配列で設定)
 - 第3引数:データフォーマット(第2引数と対応させる形で配列で指定)(%s:文字列、%d:整数、%f:浮動小数点数のいずれかを指定)
 
戻り値
- 行削除できた場合:1(削除された行数=1)
 - 削除対象行が存在しなかった場合:0(削除された行数=0)
 - エラーが発生した場合:false
 
サンプル
delete( 'table', array( 'ID' => 1 ), array( '%d' ) );
?>
wpdbクラスを用いたデータ定義
プラグインを作成する際は、専用のテーブルを定義することがあります。
その際は、以下の2種類の関数を用いて実現できます。
また、テーブル定義用の関数を実装したら、プラグインのメインファイルにて以下のように呼び出しを行い、プラグインインストール時に適用されるようにします。
任意のDDLを実行[query()]
query()メソッドを利用します。
こちらのメソッドの利用方法については、すでに説明済みのためここでは省略します。
テーブルの作成・変更[dbDelta()]
テーブルの作成・変更をしたい場合はdbDelta()関数を利用することもできます。
この関数の引数としてcreate文を渡してやると、テーブルが存在しない場合は作成し、テーブルがすでに存在する場合は差分をalter tableで反映してくれます。
ただし、利用するに当たって以下の制約があるため、標準SQLの利用に慣れている人はquery()メソッドで一本化してもよさそうに思います。
dbDelta()関数利用時の制約
実行するcreate文を作成する際に、以下の制約があります。
- 1 行につき、ひとつのフィールドを定義してください。〔訳注:ひとつの行に複数のフィールド定義を書くことはできません。さもなくば ALTER TABLE が正しく実行されず、プラグインのバージョンアップに失敗します。〕
 - PRIMARY KEY というキーワードと、主キーの定義の間には、二つのスペースが必要です。
 - INDEX という同義語ではなく、KEY というキーワードを使う必要があります。さらに最低ひとつの KEY を含めなければなりません。
 - フィールド名のまわりにアポストロフィ(')やバッククォート(`)を使ってはいけません。
 - フィールドタイプはすべて小文字であること。
 - SQL キーワード、例えば CREATE TABLE や UPDATE は、大文字であること。
 - 長さパラメータを受け付けるすべてのフィールドに長さを指定すること。例えば int(11) のように。
 - この関数を利用するためには、wp-admin/includes/upgrade.phpをインクルードする必要があります。
 
引数
- 第1引数:SQL
 
戻り値
なし。
サンプル
以下、dbDelta()関数を利用するサンプルです。
サンプル中に記述はされていませんが、設定中のテーブル名接頭辞を取得してから、登録テーブル名にも利用するといった手順を踏む方が安全です。
get_charset_collate();
    $sql = "CREATE TABLE $table_name (
        id mediumint(9) NOT NULL AUTO_INCREMENT,
        time datetime DEFAULT '0000-00-00 00:00:00' NOT NULL,
        name tinytext NOT NULL,
        text text NOT NULL,
        url varchar(55) DEFAULT '' NOT NULL,
        UNIQUE KEY id (id)
    ) $charset_collate;";
    require_once( ABSPATH . 'wp-admin/includes/upgrade.php' );
    dbDelta( $sql );
?>

