WordPressに独自のテーブルを作って読み書きするには

WordPressに独自のテーブルを作って読み書きするには

自分の環境で試したいことがあって、WordPressのDBにオリジナルのテーブルって作れるのかなーということについて調べたことをメモとしてまとめておきます。個人的に何か試すときの参考のひとつになれば、というようなスタンスで見ていただけると有難いです!


テーブル設計

まずは構想から。会議室予約みたいなのをやりたくて。最終的にはWPには不向きだなって思っちゃったんですけど。

テーブル名はrsv_timetableとし、以下のような8つのフィールド名で設定してみます。

  • id… 登録IDを格納する数値型(オートインクリメント/主キー)
  • name… 名前を格納する文字列型
  • sect… 所属を格納する文字列型
  • notes… 備考を格納する文字列型
  • time_st… 開始日時を格納する日付型
  • time_end… 終了日時を格納する日付型
  • cpt_name… 項目名を格納する文字列型
  • kwd… 削除キーを格納する文字列型

phpMyAdminでテーブル追加

140402-1-1

※クリックで拡大

WordPress(ver3.8.1)をインストールしたばかりのテーブル構造はこんな形になってます。

画面下のほうで新しいテーブルを作成することができるので、他のテーブルと同じ接続子をつけたテーブル名と、フィールドの数を入力して、実行ボタンを押します。

140402-2-1

※クリックで拡大

各フィールドを設定します。idはオートインクリメントとしておくと、自動で連番をつけてくれるので簡単です。(投稿IDとかはオートインクリメントになっています。)属性のUNSIGNEDというのは、「正の値のみを扱う」という意味です。

テーブルのストレートエンジンと照合順序は、他のテーブルに合わせておきます。

140402-3-1

※クリックで拡大

保存すると、このように新しいテーブルができました!

使うための準備

このままではまだ使えません。wp-includes/wp-db.phpの208行目あたりに、

var $tables = array( 'posts', 'comments', 'links', 'options', 'postmeta',
	'terms', 'term_taxonomy', 'term_relationships', 'commentmeta' );

このようにテーブル名を宣言している部分がありますので、

var $tables = array( 'posts', 'comments', 'links', 'options', 'postmeta',
	'terms', 'term_taxonomy', 'term_relationships', 'commentmeta', 'rsv_timetable' );

新しく作ったテーブル名を追加してやります。

こちらを参考にさせていただきました!

この方法はwp-includes内のファイルを直接編集しているので、本体のバージョンアップを考えるとあまりメンテナンス性の良いものではありません。そのため、wp-content内にdb.phpを作るという方法もあるそうです。詳しくはこちらの記事をご参照ください。

SQLの基礎知識

140402-4

テーブルの中身はこのような名称になっていて、読み書きにはSQLという言語を使います。

-- データ挿入
INSERT INTO テーブル名 SET フィールド名1 = 値1,  フィールド名2 = 値2, …
INSERT INTO テーブル名( フィールド名1, フィールド名2 … ) VALUES( 値1, 値2, … )

-- データ変更
UPDATE テーブル名 SET フィールド名 = 値 WHERE 条件

-- データ削除
DELETE FROM テーブル名 WHERE 条件

-- データ抽出
SELECT フィールド名 FROM テーブル名 WHERE 条件

よく使う構文はこのような形です。さて、ではこれをWordPressから扱ってみます!

WordPressのDBへの読み書き

ここを熟読!

方法は全部こちらに書かれています。以下は、読んでみて、実際に書いてみた上での自分なりの要約というかなんというか、そんな感じとなっております。

$wpdbを使う

WordPress にはデータベースと対話するために設定されたクラスをインスタンス化した $wpdb というグローバル変数があります。常に、このグローバル変数 $wpdb を使うようにしましょう ($wpdb をカスタム関数の中で使う前に、グローバル宣言を忘れないようにしましょう)。

Codexより。すでに用意されているのですね!もし自分で独自に関数を作ってその中で使いたい場合はグローバル宣言をしましょうということですね。

基本形

$wpdb->query("任意のSQL");

この書き方で、あらゆるSQLクエリが実行できるとされています。しかしSELECT文ではより明確な関数を使うほうが推奨されておりまして、

$data = $wpdb->get_var("SELECT …"); //変数をひとつ取り出す
$col = $wpdb->get_col("SELECT …"); //列を取り出す
$row = $wpdb->get_row("SELECT …"); //1行取り出す
$rows = $wpdb->get_results("SELECT …"); //複数行を取り出す

このように、目的に合った関数を使って取得します。

また、第三者に入力された値などを使う場合はこのままでは危険なので、prepare()を使ってエスケープ処理しなければなりません。

$wpdb->query(
	$wpdb->prepare("値を%sおよび%dで置き換えたSQL", 値1, 値2, … )
);

文字列は%s、整数は%dという文字(プレースホルダーと言うそうです)で置き換えたSQL文を先に書き、その後、そこに代入したい変数や値を順番に指定します。

INSERT文とUPDATE文には、それぞれ$wpdb->insert()$wpdb->update()という書き方もありますので、詳しくは前述のCodexをご参照ください。

例文

決まった値で書く

INSERT文を例にすると、

$wpdb->query(
	"INSERT INTO $wpdb->テーブル名
	( フィールド1, フィールド2, … )
	VALUES ( 値1, '値2', … )"
);

このように書けます。(読み易くするため改行を入れています。)フィールド1は数値型、フィールド2は文字列型という設定だとすると、値1はそのまま、値2は「’」(シングルクォーテーション)で囲います。

変数を使う

SQL文はひとつの文字列として扱わなければいけないので、値に変数を使いたい場合は、文字列と変数を連結してやらねばなりません。

$wpdb->query(
	"INSERT INTO $wpdb->テーブル名
	( フィールド1, フィールド2, … )
	VALUES ( " . $data1 . ", '" . $data2 . "', … )"
);

信頼できない変数を使う

第三者に入力された値などを使う場合。prepare()を使って書いてみます。

$wpdb->query(
	$wpdb->prepare(
		"INSERT INTO $wpdb->テーブル名
		( フィールド1, フィールド2, … )
		VALUES ( %d, %s, … )",
		$data1, $data2, …
	)
);

クォート文字で囲む必要はないとのことなので、連結させるより楽ですねー。

合否判定

MySQLエラーが発生した場合falseが返ってくるので、

$sql_rsl = $wpdb->query("任意のSQL");
if ( $sql_rsl == false ) {
	echo '処理に失敗しました。';
} else {
	echo '成功しました。';
}

このように処理メッセージを出すことも出来ます。

さっき作ったテーブルを例に

データ挿入

140402-5
$ipt_name = '鈴木'; //名前
$ipt_sect = '設計'; //所属
$ipt_notes = '経営会議'; //備考
$ipt_time_st = '2014-03-24 09:30:00'; //開始時間(MySQLのDATETIMEフォーマットで)
$ipt_time_end = '2014-03-24 12:30:00'; //終了時間
$ipt_cpt_name = '会議室D'; //項目名
$ipt_kwd = 'aaa'; //削除キー
//以上の変数へ入力された情報が格納されているとする

$sql_rsl = $wpdb->query( $wpdb->prepare(
	"INSERT INTO $wpdb->rsv_timetable
	( name, sect, notes, time_st, time_end, cpt_name, kwd )
	VALUES ( %s, %s, %s, %s, %s, %s, %s )",
	$ipt_name, $ipt_sect, $ipt_notes, $ipt_time_st, $ipt_time_end, $ipt_cpt_name, $ipt_kwd
) );

if ( $sql_rsl == false ) {
	echo '登録に失敗しました。';
} else {
	echo '登録しました。';
}

idは自動で番号を振ってくれるオートインクリメントにしてあるので、指定する必要はありません。id以外はみんな数値じゃないので、プレースホルダーは%sになります。

UPDATE文は今回使わなかったので割愛しますが、INSERTと似てますね。

DELETE

140402-6
$id = 1; //削除したいレコードのID

$sql_rsl = $wpdb->query( $wpdb->prepare(
	"DELETE FROM $wpdb->rsv_timetable WHERE id = %d",
	$id
) );

if ( $sql_rsl == false ) {
	echo '削除に失敗しました。';
} else {
	echo '削除しました。';
}

idというフィールドは数値型なので、プレースホルダーは%dを使います。

SELECT

複数行を取得

140402-7
$ipt_cpt_name = '会議室A' //項目名

$results = $wpdb->get_results( $wpdb->prepare(
	"SELECT *
	FROM $wpdb->rsv_timetable
	WHERE cpt_name = %s",
	$ipt_cpt_name
) );

if ( $results ) { //該当データがあるときだけ
	foreach ( $results as $value ) { //該当データ数繰り返す
		echo $value->id; //IDを出力
		echo $value->name; //名前を出力
		echo $value->sect; //所属を出力
	}
}

項目名が「会議室A」のものを全て取得して、任意のフィールドを出力するサンプル。レコードが複数なのでforeachを使う必要があります。

SELECTで全てのフィールドを指定したいときは、*を使うと簡単です。

1行を取得

140402-8
$ipt_id = 3 //ID

$row_data = $wpdb->get_row( $wpdb->prepare(
	"SELECT * FROM $wpdb->rsv_timetable WHERE id = %s",
	$ipt_id
) );

echo $row_data->name; //名前を出力
echo $row_data->sect; //所属を出力

指定IDのレコードを取得して、任意のフィールドを出力するサンプル。

列(フィールド)を取得

140402-9
$ipt_id = 3 //ID

$kwd = $wpdb->get_col( $wpdb->prepare(
	"SELECT kwd FROM $wpdb->rsv_timetable WHERE id = %d",
	$ipt_id
) );

echo $kwd[0]; //削除キーを出力

指定IDの1つのフィールドだけ持ってきて出力するサンプル。列を取得するget_col()は配列を返してくるので、ひとつだけ欲しくても[0]ってつけないと出てこないっぽい…。

$kwd = $wpdb->get_var( $wpdb->prepare(
	"SELECT kwd FROM $wpdb->rsv_timetable WHERE id = %d",
	$ipt_id
) );

echo $kwd; //削除キーを出力

1つの値だけが欲しい場合はこっちのget_var()のほうが良いのかな。配列じゃなく、ひとつの変数として取得できます。

参考記事

こちらの記事を参考にさせていただきました。いつも本当にありがとうございます。・゚・(ノД`)・゚・。

公開日:2014/04/02
更新日:2014/05/22

2件のピンバック

  1. […] WordPressに独自のテーブルを作って読み書きするには *Ateitexe […]


コメントを残す

メールアドレスが公開されることはありません。 が付いている欄は必須項目です

このサイトはスパムを低減するために Akismet を使っています。コメントデータの処理方法の詳細はこちらをご覧ください

コメントは承認制ですので、反映までしばらくお待ち下さい。(稀にスパムの誤判定にて届かないこともあるようですので、必要な際はお問い合わせからお願い致します。)

YouTubeでQ&Aコンテンツを企画しています

運営しているYouTubeチャンネルで、ご相談やご質問を募集しています。動画のコメントやお問い合わせページからお気軽にご相談をお寄せください。