fbpx

メニュー

wpdb道場 (5) 〜開発の土台を作ろう〜

高橋文樹 高橋文樹

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

前回までで理解が深まってきました。そろそろ作り始めましょう。今回は新テーマTwenty Fifteenの子テーマと、プラグインを同時に開発していきます。「どのような機能をプラグインにわけるか」ということもできれば一緒に知っておきたいところです。

その前にサイトをインストールしましょう。ローカルになんでもいいのでインストールし、日本語のテーマユニットテストのデータを放り込んでください。やり方はこうです。

  1. ローカルにWordPressをインストール。URLはなんでもいいです。僕はホストの設定を行い、 http://tweeter.jp にインストールしました。
  2. プラグインでWordPress Beta Tester, Debug Bar, Debug Bar, Debug-Bar-Extenderというのをインストールして、全部有効化してください。
  3. 管理画面のツール > ベータテストに移動し、ポイントリリース・ナイトリービルドをえらんでください。そうすると、「更新」に赤いラベルが出ます。さっそくWordPressを更新。僕の場合は4.2-alphaと出ました。
  4. 日本語版テーマユニットテストのデータをWordPress Importerを使ってインポート。「添付ファイルをダウンロードする」にチェックを忘れずに。あと、ユーザーも一緒にインポートしてください。

これで準備が整いました。続いて、テーマとプラグインを作りましょう。

テーマの作成

wp-content/themesにtweeterというフォルダを作成。style.cssをこんな感じで書きます。

/*
Theme Name: Tweeter
Theme URI: https://tweeter.jp
Template: twentyfifteen
Author: Takahashi Fumiki
Author URI: https://wordpress.org/
Description: Child theme of Twenty Fifteen.
Version: 1.0
License: GNU General Public License v2 or later
License URI: http://www.gnu.org/licenses/gpl-2.0.html

This theme, like WordPress, is licensed under the GPL.
Use it to make something cool, have fun, and share what you've learned with others.
*/

これでTweeterがテーマとして認識されますので、有効化してください。今後、「テーマ」といった場合、このTweeterを指すことにします。子テーマに自信がない人はCodexをどうぞ。

なお、このテーマはGithubに置いてあるのでチェックアウトすれば済むともいえますが、それだとあんまり勉強にならないかもしれません。

プラグインの作成

続いてプラグインを作成しましょう。プラグインの名前はfreundschaftにしましょう。ドイツ語で「友情」という意味だったと思います。ユーザーをフォローしたからといって友情が生まれるのかというと、はなはだ心もとないですが……

それでは、wp-content/pluginsフォルダにfreundschaftというフォルダを作り、その中にfreundschaft.phpというファイルを作りましょう。中身はこんな感じ。

<?php
/*
Plugin Name: Freundschaft
Plugin URI: https://github.com/hametuha/freundschaft
Description: Following each other, then you are friends.
Author: Hametuha inc.
Version: 1.0
Author URI: http://hametuha.co.jp
License: GPL2 or Later
*/

こうすると、プラグインリストに追加されるようになります。それでは、freundschaftを有効化しましょう。まだ何も起きませんが、「プラグインが有効化されました」と出ると嬉しいですね。

ちなみに、このプラグインもgithubに置いてあります。

データベースを作ろう

では、前回定義したデータベースを作りましょう。テーブルの構造はこんな感じでしたね。

wp_followers
follower_id user_id created
1 2 2014-12-10 21:00:00
2 1 2014-12-11 09:00:00
3 1 2014-12-13 12:30:00

はて、このテーブルを作るのはいいとして、いつ作ればいいんでしょうか? これはけっこう悩ましい問題です。

3.0とかそれぐらいまでは register_activation_hook という関数を使うと、プラグインが有効化したときに必ず走るフックが実行できたので、このときにテーブルを作ればよかったのです。

一括アップグレードしたときなど、プラグインは一度無効化されてからアップデート後に再度有効化されるのですが、3.1ぐらいからフックが走らなくなりました。

さて、どうしましょう。僕はプラグインやテーマが必ず設定を行えるフックが存在してもいいと思っているのですが、以前どこかで見た記事で、コアコミッターが「admin_init使え」といっていました。したがって、admini_initを使うことにします。

freundschaft.php にこんなコードを書いてみましょう。

add_action(‘admin_init’, function(){
     var_dump(‘freundschaft!’);
});

admin_initフックでプラグイン名を高らかに宣言するというコードですね。実際に管理画面にアクセスしてみると、上の方に表示されています。

admin_initフックで実行
admin_initフックで実行

なるほど、ここでテーブルを作成すればいいはわかりました。しかし、毎回テーブル作るのもバカらしいですよね。こういう場合はこんなセオリーがあります。

  1. まず、設定にテーブルのバージョンを保存しておく。なければ0と判定。
  2. 現在のテーブルのバージョンと設定に保存されたテーブルのバージョンを見比べて、現在のテーブルのバージョンの方が新しければ、テーブルを作成またはアップデートする。
  3. アップデートが終わったら、現在のテーブルのバージョンを設定として保存しておく。

こういうふうにすれば、無駄に何度もテーブル作成されることはありません。コードをこんな風に書き直しましょう。get_optionとupdate_optionはそれぞれ設定値を更新するための関数ですね。

add_action('admin_init', function(){
     // このプラグインのいまのバージョン
     $current_version = '1.0';
     // データベースに保存されているバージョン
     // 二つ目の引数はオプションが存在しないときの初期値
     $db_version = get_option('freundschaft_table_version', 0);
     if( version_compare($current_version, $db_version, '>') ){
          // データベースが古いので、テーブルを作成!
          echo 'テーブルを作るよ';
          // 現在のバージョンを保存
          // まだコメントアウトしておいてください。
          //update_option('freundschaft_table_version', $current_version);
     }
});

どうでしょう、アクセスするたび「テーブルを作るよ」と表示されますね。

dbDeltaを使う

さて、MySQLにはテーブルを作成する場合CREATE TABLE、テーブルを更新する場合はALTER TABLEという構文を使います。

では両方書かなければいけないのかというと、そんなことはなく、dbDeltaという便利な関数があります。これはCREATE TABLEのクエリを受け取ると、テーブルがすでに存在する場合、それをUPDATE文に書き換えてくれるんですね。ちょっと挙動が謎なのですが、便利なやつです。

それでは、前回考えたテーブル構造をCREATE TABLE文にするとこんな感じです。

CREATE TABLE wp_followers (
     follower_id BIGINT NOT NULL,
     user_id BIGINT NOT NULL,
     created DATETIME NOT NULL,
     PRIMARY KEY (follower_id, user_id)
) ENGINE=InnoDB CHARACTER SET UTF8;

CREATE TABLE文はテーブル名、カラム、キー、エンジン、文字キャラクターセットという感じです。ぱっと見でわかりますよね? わからない人はMySQLのマニュアルをどうぞ。

それでは、これを実行してみましょう。一気に次の処理も行います。

  • Ajaxのときはそもそも実行しない(Ajaxもadmin_initフックを通るので)
  • テーブル名はユーザーの環境によって接頭辞が変わるので、変数にした方がよい
  • dbDeltaは普段読み込まれないファイルに書いてある関数なので、それを読み込む
  • テーブルが更新されたら更新された旨を表示
add_action('admin_init', function(){
     // Ajaxなら何もしない
     if( defined('DOING_AJAX') && DOING_AJAX ){
          return;
     }
     // このプラグインのいまのバージョン
     $current_version = '1.0';
     // データベースに保存されているバージョン
     $db_version = get_option('freundschaft_table_version', 0);
     if( version_compare($current_version, $db_version, '>') ){
          // データベースが古いので、テーブルを作成!
          // $wpdbを呼び出し
          global $wpdb;
          $table_name = "{$wpdb->prefix}followers";
          $query = <<<SQL
               CREATE TABLE {$table_name} (
                    follower_id BIGINT NOT NULL,
                    user_id BIGINT NOT NULL,
                    created DATETIME NOT NULL,
                    PRIMARY KEY (follower_id, user_id)
               ) ENGINE=InnoDB CHARACTER SET UTF8;
SQL;
          // dbDeltaのためのファイルを読み込み
          require_once ABSPATH.'/wp-admin/includes/upgrade.php';
          dbDelta($query);
          // 現在のバージョンを保存
          update_option('freundschaft_table_version', $current_version);
          // 管理画面にメッセージを表示
          add_action('admin_notices', function() use ($table_name, $current_version){
               printf('<div class="updated"><p>%sを%sに更新しました。</p></div>', $table_name, $current_version);
          });
     }
});

さて、これで管理画面にアクセスすると、こんな表示が出ました! やったー!

更新メッセージが出たぞ!
更新メッセージが出たぞ!

しかし油断は禁物。もしかしたらテーブルが作成されていないかもしれません。おもむろにphpMyAdminなどを開いてみましょう。ぼくはSequelProというのを使っています。

SequelProで見たテーブル
SequelProで見たテーブル

おっ、どうやらできていますね。

ちなみに、勘がいい人は右上のデバッグバーが赤になっているのに気付いたかと思いますが、dbDeltaはテーブルの存在チェックで必ずエラーを吐きます。これ、直した方がいいと思うんですけどね。なんでしょう。

なにはともあれ、テーブルを作成することができました。次回移行、テーブルにデータを挿入する方法を考えていきたいと思います。それでは、これからお寿司を食べに行くので、この辺で。

サイトの拡張性を飛躍的に高める WordPressプラグイン開発のバイブル

価格¥2,593

順位355,718位

宮内 隆行, 西川 伸一, 岡本 渉, ほか

発行SBクリエイティブ

発売日2014 年 7 月 19 日

Amazonを開く

Supported by amazon Product Advertising API

すべての投稿を見る

高橋文樹ニュースレター

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