fbpx

メニュー

wpdb道場 (1) 〜はじめての$wpdb〜

高橋文樹 高橋文樹

この投稿は 9年半 前に公開されました。いまではもう無効になった内容を含んでいるかもしれないことをご了承ください。

唐突に連載を開始します。現在、破滅サロンにはある程度自由に使える会議室(ギュウギュウ詰めで30人入る)が付帯しているので、そこで開催予定の講座の下準備です。

さて、最近はWordPressでWebアプリケーションを作ろうとか、そんな回りくどいことするなバカとか、そういった議論が巻き起こっていますね。知りませんか? そうですか……

ともあれ、WordPressをブログとかけはなれた用途で使うとそりゃ悪手だな、蟻ん子と言われてしまいますが、ブログ+αで拡張していきたいという要望はわりと多いと思います。

その時立ちはだかるのがデータベース操作の壁。

プラグインでなんとかなるならそれでもいいですが、自分でデータベースを操作できると全能感に満ち溢れた楽しいWebライフが送れること請け合いです。そんな全能感を満たしてくれる機能の入り口が$wpdbという魔法の変数なのですね。

はい、これで導入部は終わりです。

対象とする読者

この一連の記事はWordPressを使ってサイトを運営していて、既存プラグインで解決できないような問題を抱えている人を対象にしています。求められるのはHTML・CSS・JS・PHPの基礎知識と、ググることを恐れない勇気です。

最終的なゴール

WordPressを会員制サイトとして運営している想定とします。で、フォローしたりフォローされたりブロックしたり、自分のフォロワーを眺めて悦に入ったりできるプラグインを作成します。

もし余力があれば、ダイレクトメッセージを送るところまでやりたいなと思いますが、それは皆さんの反応次第です。

それでは、開始しましょう。

1. WordPressはデータをどのように永続化しているか

WordPressは多くのデータをMySQLというデータベースに保存して永続化しています。この「データの永続化」という概念は重要なので覚えておいてください。

たとえば、テーマを選択し、デフォルトのTwenty Fourteenからオリジナルテーマのtakahashifumikiに変えたとしましょう。そうすると、このデータはこんな風に保存されます。

MySQLに保存されたデータ。SequeryProを使用。
MySQLに保存されたデータ。SequeryProを使用。

wp_optionsというテーブルにtemplateとstylesheetというオプション名で保存されていますね。このうち、templateが親テーマで、stylesheetが子テーマです。親子テーマを使っている場合は、別の値が入ることになります。

WordPressはこれらの情報を読み込むことで誰が見ても同じテーマを選択し、テーマを変更したら次からそのテーマで表示されるという「当たり前の機能」を提供しています。

2. $wpdbとは?

では、WordPressを動作させているPHPからMySQLを操作するにはどうするのかというと、ひと昔前の『PHP + MySQLでSNSを作ろう!』みたいな本にはこんなことが書いてありました。

<?php
// MySQLに接続
$link = mysql_connect('localhost', 'mysql_user', 'mysql_password');
if ( !$link ) {
    die('接続できませんでした: ' . mysql_error());
}
echo '接続に成功しました';
// クエリを発行
$result = mysql_query("SELECT * FROM wp_posts WHERE post_status = ‘10'");
if( $result ){
    while( $row = mysql_fetch_assoc($result) ){
        // 投稿を出力
        printf(‘%s %s‘, $result[’post_title’], $result[‘post_date']);
    }
}else{
    echo ‘投稿を取得できませんでした。';
}
// MySQLを終了
mysql_close($link);

今日日、こんなレガシーなことをやることはないと思いますが、とにかく、WordPressもこうした一連の面倒くさい処理を行っているわけです。だったら、自分でこんな面倒くさいことやらなくても、WordPressがやっているものを使わせて貰えば済みますね。

その入り口が$wpdbなわけです。主な機能は次の通り。

  • MySQLへの接続
  • クエリの発行、結果の取得
  • 値のエスケープ

$wpdbは元がezSQLという個人開発の小さなライブラリなので、他のフレームワークと比べるとはるかに貧弱な機能しか持っていません。ただ、それゆえに気軽に使い始められます。

3. SQL文を発行してみよう!

それでは、SQL文を発行して、結果を見てみましょう。環境を用意するのがめんどくさいので、いまあなたが運用しているWordPressのルートフォルダにwpdb-test.phpというファイルをアップロードして、その中身を編集するというワイルドな方法でいきます。

まず、冒頭でwp-load.phpを読み込んで、クエリを発行します。

<?php
// これでWordPress関数がほとんど使えるようになる!
include 'wp-load.php';
// wp_optionsテーブルから10件を取得
$results = $wpdb->get_results("SELECT * FROM wp_options LIMIT 10”);
// 結果を表示
var_dump($results);

これで http://example.com/wpdb-test.php にアクセスしてみると、設定情報がずらっと表示されます。よかったですね。

オプションに保存された値
オプションに保存された値

ただし、上のクエリにはいくつかおかしな点があります。オプション値を取得する関数はすでにWordPressに用意されているというのはおいておくとしても、テーブル名を直に書いていますね。

テーブル接頭辞はインストールするときにユーザーが選ぶことができるので、人によっては動いたり動かなかったりしてしまいます。でも大丈夫。$wpdbならね。

//$results = $wpdb->get_results("SELECT * FROM wp_options LIMIT 10”);
$results = $wpdb->get_results("SELECT * FROM {$wpdb->options} LIMIT 10”);

$wpdbはそのプロパティとしてWordPressのデフォルトのテーブル名を持っています。したがって、$wpdbを利用する限りは環境によって悩まなくてもいいわけです。$wpdb->optionsと書けば、接頭辞+optionsになります。リロードしてみると同じ結果が表示されます。

ちなみに、テーブル接頭辞は$wpdb->prefixで、マルチサイトインストール時のグローバルプレフィックスは$wpdb->base_prefixで取れます。

4. 条件を絞って集計してみよう!

それでは、続いてMySQLの強力な機能のうち、集約関数を利用してみましょう。公開済みの投稿の本文の文字数を合算してみます。投稿本文はwp_postsのpost_contentに保存されています。

// 公開済み投稿の本文の長さを全部足す
$query = <<<SQL
     SELECT SUM(CHAR_LENGTH(post_content))
     FROM {$wpdb->posts}
     WHERE post_status = 'publish'
       AND post_type = 'post'
SQL;
$total = $wpdb->get_var($query);

var_dump($total);

CHAR_LENGTHは指定したカラムの文字長を得る関数で、SUMは合算する関数です。PHPやJSなどと異なるのは、関数の対象が該当する行のカラムになる点。

また、さきほどと異なるのは、$wpdb->get_resultsではなく、$wpdb->get_varを使っているところでしょうか。

get_resultsは該当する行のすべてを取得します。その一方、get_varは該当する行の最初の列だけを取得します。

行のすべてを取得してしまうと、PHP側でforeachとかを使って再度取得しなければいけないのが面倒くさいですね。そんなときget_varが便利です。

合計が出ました(厳密には違うんですけどね)
合計が出ました(厳密には違うんですけどね)

さて、合計は取れたので、今度は平均を取ってみましょう。先ほどのクエリをちょろっと変えます。

// 公開済み投稿の本文の長さを平均値を出す
$query = <<<SQL
     SELECT AVG(CHAR_LENGTH(post_content))
     FROM {$wpdb->posts}
     WHERE post_status = 'publish'
       AND post_type = 'post'
SQL;
$average = $wpdb->get_var($query);

var_dump($average);

AVGが平均を取る関数ですね。どうでしょう、出ましたか? よかったですね。

5. まとめ

この記事でわかったのは以下の2点です。

  1. $wpdbというのがMySQL操作の入り口
  2. 集計とかできるっぽい

wpdb-test.phpはそれ自体だと特にリスクはないので、消しても消さなくてもどっちでもいいです。見つかっても「バカだなあ」と思われるぐらいかと。念のため、ソース全体をGistにあげておきます。

次回はデータの追加および削除をやってみましょう。一応、続きは明日アップ予定。wpdb道場というタグも用意しました。終わり。

すべての投稿を見る

高橋文樹ニュースレター

高橋文樹が最近の活動報告、サイトでパブリックにできない情報などをお伝えするメーリングリストです。 滅多に送りませんので、ぜひご登録お願いいたします。 お得なダウンロードコンテンツなども計画中です。