4
2

More than 1 year has passed since last update.

【WordPress】WordPress から DB を操作する

Last updated at Posted at 2022-01-31

今回は 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 というグローバル変数を用いてアクセスします。

function.php
global $wpdb;

INSERT

新たにデータを挿入する場合は insert 関数を用います。
使い方は以下の通りです。

構文:$wpdb->insert( $table, $data, $format );

$table :テーブル名(文字列)
$data:挿入するデータ(配列)
$format:挿入するデータのフォーマット(配列)

以下の例はユーザーが名前、メールアドレス、学年を入力し、session_id とともに送信してテーブルに保存するものです。
サーバー側で受け取ったデータを $PostArray 変数に格納し,
ここから一つずつ取り出してテーブル挿入用の配列にセットして insert します。

function.php

// テーブルに挿入
$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 の値を参照してデータを更新する例です。

function.php

// データを更新
$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 処理の例です。

function.php
// 送信された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

4
2
0

Register as a new user and use Qiita more conveniently

  1. You get articles that match your needs
  2. You can efficiently read back useful information
  3. You can use dark theme
What you can do with signing up
4
2