ワードプレスでwpdbクラスを使ったDB操作方法

ワードプレスにおいて、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 );
?>