今回は WordPress からDB(データベース)にアクセスして UPDATE と INSERT 処理を行う方法をご紹介します。
また UPSERT 処理(UPDATE + INSERT)を行う方法についても合わせてご紹介します。
環境
WordPress: 4.9.19
PHP:7.0.27
MySQL:5.6.38
DB設計
今回扱うサンプルのテーブルを作成します。
このテーブルでは学生の情報(名前、メールアドレス、学年)を管理することとします。
session_id
は UPDATE 処理を行う際にキーとして用います。
CREATE TABLE wp_test (
id INT(11) UNSIGNED NOT NULL AUTO_INCREMENT COMMENT 'ID',
name VARCHAR(30) NOT NULL COMMENT '名前',
mail VARCHAR(30) NOT NULL COMMENT 'メールアドレス',
grade TINYINT(3) UNSIGNED DEFAULT NULL COMMENT '学年',
session_id VARCHAR(100) NOT NULL COMMENT '更新用のセッションID',
created_at DATETIME NOT NULL DEFAULT CURRENT_TIMESTAMP COMMENT '登録日時',
updated_at DATETIME NOT NULL DEFAULT CURRENT_TIMESTAMP ON UPDATE CURRENT_TIMESTAMP COMMENT '更新日時',
PRIMARY KEY(id),
KEY `idx_ws_01` (`session_id`),
UNIQUE KEY `uk_ws_01` (`session_id`)
) ENGINE=InnoDB DEFAULT CHARSET=utf8mb4 COLLATE=utf8mb4_bin COMMENT='テストテーブル';
DBアクセス
WordPress には wpdb
というクラスが用意されており、ここに含まれる関数で DB を操作することができます。
このクラスは直接呼び出すことはできないので以下のように $wpdb
というグローバル変数を用いてアクセスします。
global $wpdb;
INSERT
新たにデータを挿入する場合は insert
関数を用います。
使い方は以下の通りです。
構文:$wpdb->insert( $table, $data, $format );
$table
:テーブル名(文字列)
$data
:挿入するデータ(配列)
$format
:挿入するデータのフォーマット(配列)
以下の例はユーザーが名前、メールアドレス、学年を入力し、session_id
とともに送信してテーブルに保存するものです。
サーバー側で受け取ったデータを $PostArray
変数に格納し,
ここから一つずつ取り出してテーブル挿入用の配列にセットして insert
します。
// テーブルに挿入
$wpdb->insert(
'wp_test',
array(
'name' => $PostArray['name'],
'mail' => $PostArray['mail'],
'grade' => $PostArray['grade'],
'session_id' => $PostArray['session_id']
),
array('%s', '%s', '%d', '%s')
);
第2引数の配列は「テーブルのカラム名 => 挿入するデータ」の形式でカラムごとに配列の要素を書いていきます。
第3引数の配列には第2引数に対応する形で各データのフォーマットを指定します。
例えば配列の1番目には name
カラムに対応する %s
(文字列)を指定し、3番目には grade
カラムに対応する %d
(整数) を指定しています。
なおフォーマット形式は以下の3つの中から指定します。
-
%s
:文字列 -
%d
:整数 -
%f
:浮動小数点数
ちなみに省略すると挿入するデータはすべて文字列として扱われます。
また、テーブルのカラム名と挿入するデータは両方とも SQL エスケープしてはいけません。
これは insert
関数内部でエスケープ処理が行われるためです。
insert
関数の内部では _insert_replace_helper
という名前の関数が実行され、さらにその中ではprepare
関数によってエスケープ処理が施されたうえで INSERT 文が実行されるようになっています。
_insert_replace_helper
関数のソースコードはこちらをご覧ください。
https://developer.wordpress.org/reference/classes/wpdb/_insert_replace_helper/
UPDATE
既存のデータを更新するには update
関数を使います。
使い方は以下の通りです。
構文:$wpdb->update( $table, $data, $where, $format = null, $where_format = null );
$table
:テーブル名(文字列)
$data
:更新後のデータ(配列)
$where
:WHERE句に使うカラムと値(配列)
$format
:更新後のデータのフォーマット(配列)
$where_format
:$where
に使う値のフォーマット(配列)
第2引数の $data
には INSERT の場合と同じように「テーブルのカラム名 => 更新するデータ」の形式で配列を作成して渡します。
第3引数の $where
には更新するデータの条件をキーと値のペア(配列形式)で指定します。
これは SQL の WHERE 句の条件文に該当する部分です。
複数個指定すると AND でつながれます。
第5引数の $where_format
は $where
で指定した値のフォーマットを指定します。
省略した場合はすべて文字列として扱われます。
また、$data
と $where
に渡すカラム名とデータは両方とも事前にエスケープ処理してはいけません。
以下は session_id
の値を参照してデータを更新する例です。
// データを更新
$wpdb->update(
'wp_test',
array(
'name' => $PostArray['name'],
'mail' => $PostArray['mail'],
'grade' => $PostArray['grade'],
'session_id' => $PostArray['session_id']
),
array(
'session_id' => $PostArray['session_id']
),
array('%s', '%s', '%d', '%s'),
array('%s')
);
第3引数のキーに session_id
を、値に $PostArray['session_id']
を指定することで、送信された session_id
と同じ session_id
を持つデータ(行)を更新しています。
UPSERT
最後に UPSERT を行う方法についてご紹介します。
UPSERT とは特定の値を持つデータ(行)がテーブルにあれば UPDATE し、なければ INSERT する処理のことです。
今回は送信された session_id
がテーブルにあるか否かを確認し、結果に応じて INSERT および UPDATE を実行します。
特定の値の有無を確認するために今回は get_var
関数を用いています。
get_var
関数の使い方は以下の通りです。
構文:$wpdb->get_var( $query, $column_offset, $row_offset );
$query
:実行したい SQL(文字列)
$column_offset
:何列目の値を返すか(一つ目は0、初期値は0)(整数)
$row_offset
:何行目の値を返すか(一つ目は0、初期値は0)(整数)
この関数は第1引数の $query
で記述した SQL の実行結果を一つだけ返却します。
もし実行結果に該当する値がなければ NULL
が返されます。
また、通常 SQL は複数の行と列に渡る値を返却しますので $column_offset
と $row_offset
で何行何列の値を返すかを指定します。
何も指定しなければ先頭の値(0行0列)が返却されます。
そのため今回のように一意性制約のある値を取得する場合は無指定で問題ないと思います。
以下は UPSERT 処理の例です。
// 送信されたsession_idと同じ値を持つ行のidを取得
$targetId = $wpdb->get_var($wpdb->prepare("SELECT id FROM wp_test WHERE session_id = %s", $PostArray["session_id"]));
if (is_null($targetId)) {
// targetIdがNULLならデータを追加
$wpdb->insert(
'wp_test',
array(
'name' => $PostArray['name'],
'mail' => $PostArray['mail'],
'grade' => $PostArray['grade'],
'session_id' => $PostArray['session_id']
),
array('%s', '%s', '%d', '%s')
);
} else {
// targetId が NULL でなければデータを更新
$wpdb->update(
'wp_test',
array(
'name' => $PostArray['name'],
'mail' => $PostArray['mail'],
'grade' => $PostArray['grade'],
'session_id' => $PostArray['session_id']
),
array(
'session_id' => $PostArray['session_id']
),
array('%s', '%s', '%d', '%s'),
array('%s')
);
}
get_var
関数の$query
にはSQLインジェクション対策として prepare
関数を用いています。
prepare
関数の使い方はこちらを参考にしてください。
関数リファレンス/wpdb Class - WordPress Codex 日本語版
get_var
関数は SQL によって何も取得できなければNULL
が返却されますので、結果が NULL
だった場合は INSERT を、 NULL
ではなかった場合は UPDATE を実行するようにしています。
UPSERT処理は以上です。
最後までお読みいただきまして、ありがとうございました。
参考
関数リファレンス/wpdb Class - WordPress Codex 日本語版
wpdb::_insert_replace_helper() | Method | WordPress Developer Resources