WordPressのプラグイン作成 第二回

WordPress のプラグイン作成 — $wpdb 編 その1 –

posted at 2014/01/15 by denpoya@コワーキングスペース町田

今回は、WordPressにデータベースのテーブルを作成してもらうことが主なテーマです。その時使う$wpdbやWordPressの関数dbDelta()update_option()get_option()の使い方にも触れておきます。

さらに、テーブルの数が複数になった時にforeach文で回すための工夫もしておくことにしましょう。バージョンが上がって、テーブルを増やさなければならなくなった時でも簡単に対処できるようになるでしょう。

WordPressにテーブルを作ってもらう

WordPressにテーブルを作ってもらうのはいつどの場面でしょうか?プラグインを「有効化」した時の1回だけでよいですか?

プラグインの新しいバージョンを作成する際、別のテーブル構造が必要になったらアップグレード用関数を作成することになるでしょう。フィールド属性を変更するだけでなく、新しいテーブルを追加することもあるかもしれません。そのようなことを念頭に置いてコーディングしていきます。

WordPressが通常使っているテーブルではなく、私たちのプラグイン専用のテーブルを「有効化」のタイミングで作成することにします。本当に専用のテーブルが必要かどうかは検討すべきでしょう。このプラグインには必要である、という設定でお話を進めていきます。

WordPressをインストールするときにテーブル名のプレフィックス(接頭辞)を指定できました。私たちのテーブル名にも同じプレフィックスをつける必要があるでしょう。デフォルトは「wp_」ですがインストールする人によって異なるプレフィックスになっているかもしれません。

まず、第1段階として

  1. 「テーブル名に付けられているプレフィックスを私たちのテーブルにも付ける」
  2. 「私たちのテーブルが既に存在しているかを確認しておく」

この2つからコーディングしていきます。必要なものは$wpdbです。

WordPressのデータベース操作用のクラス関数 wpdb

WordPressにはデータベース操作用のクラス関数が用意されています。

しかしそれを直接使うのではなく、WordPressにはデータベースと対話するために設定されたクラスをインスタンス化した$wpdbというグローバル変数が用意されているのでこのグローバル変数$wpdbを使うのが良いようです。

そのためにはグローバル宣言をします。

global $wpdb;

$wpdbの持つメソッドのうちよく使うのが、get_var('query',column_offset,row_offset)get_results('query', output_type)そしてquery('query')といったSQL文を発行するメソッド、その時にSQLインジェクション攻撃からクエリを保護するために使うprepare( 'query'[, value_parameter, value_parameter ... ] )メソッドとSQLエスケープのためのescape($user_entered_data_string)ではないでしょうか。説明は関数を使う時にしましょう。

テーブル名にプレフィックスをつける

テーブル名に付けられているプレフィックスは、

$wpdb->prefix;

という変数に格納されています。例えば、「example_table」という名前にプレフィックスをつけてテーブル名にしたいならば、

$table_name = $wpdb->prefix . 'example_table';

のようにします。

テーブルが既に存在しているかどうかを確認する

テーブルが既に存在しているかどうかを確認するのには、

$is_db_exists = $wpdb->get_var($wpdb->prepare("SHOW TABLES LIKE %s", $table_name));

のように「SHOW TABLES LIKE テーブル名」クエリを発行します。prepareメソッドによって、「%s」には第2引き数の文字列がその箇所に挿入されます(2つ目の「%s」があったら第3引き数の値が挿入されます)。

get_varメソッドはデータベースから変数を一つ返します。変数は一つしか返ってきませんが、クエリの結果はあとから使うことができます。結果にマッチするものがない場合、NULL が返されます(関数リファレンス/wpdb Classを参照、以下同様)。

テーブルがないときには作成するようにします。

CDPluginクラスのactivate()メソッドを実装

前回作成したCDPluginクラスのactivate()メソッドを編集します。既に述べたことから下のようになるでしょう。

  • CDPlugin.php
<?php
class CDPlugin {
    function __construct() {
    }

    function activate() {
        $table_name = $wpdb->prefix . 'main_master';
        $is_db_exists = $wpdb->get_var($wpdb->prepare("SHOW TABLES LIKE %s", $table_name));

        if ($is_db_exists == $table_name) {
            return;
        }

        // ここでSQLクエリの実行する

    }
}
SQLクエリの実行

直接SQLクエリを実行($wpdb->query($sql))してもよいのですが、wp-admin/include/upgrade.phpで定義されているdbDelta関数を使う方がよいようです。dbDelta関数現在のテーブル構造を走査し、作成予定のテーブルと比較、必要に応じてテーブルを追加・修正します。更新にはとても便利な関数です(Creating Tables with Plugins(日本語版)を参照)。ただし、使用するには少しばかり癖があるようです。

参考にさせていただいた上記リンクとその最新版であるCreating Tables with Plugins(最新英語版)のページを見ると日本語版よりも癖がもう一つ増えて4つ項目が並んでいます。

  1. 1行につき1つのフィールドを定義してください。 〔訳注:一つの行に複数のフィールド定義を書くことは出来ません。さもなくば ALTER TABLEが正しく実行されず、プラグインのバージョンアップに失敗します。 〕
  2. PRIMARY KEYと主キーの定義の間には二つのスペースが必要です。〔訳注:原文 "You have to have two spaces between the words PRIMARY KEY and the definition of your primary key."〕
  3. INDEXという言葉ではなく、KEYという言葉を使う必要があります。
  4. フィールド名をアポストロフィやバッククォートで囲ってはいけません。〔原文:"You must not use any apostrophes or backticks around field names. "〕

このことに気を付けてSQL文を次のように作ります。dbDelta関数を使うには、wp-admin/include/upgrade.phpをインクルードする必要があります。

発行するSQL文を次のようにし、dbDelta関数を実行させます。

$sql = "CREATE TABLE " . $table_name . " (
     id mediumint(9) NOT NULL AUTO_INCREMENT,
     name tinytext NOT NULL,
     url VARCHAR(55) NOT NULL,
     created timestamp NOT NULL DEFAULT CURRENT_TIMESTAMP ON UPDATE CURRENT_TIMESTAMP COMMENT '作成日',
     modified timestamp NOT NULL DEFAULT '0000-00-00 00:00:00' COMMENT '修正日',
     UNIQUE KEY id (id)
     );";

require_once(ABSPATH . 'wp-admin/includes/upgrade.php');
dbDelta($sql);
バージョン管理

合わせて私たちのテーブルのバージョン管理の仕組みも用意します。プラグインを一度「停止」してもらい、再び「有効化」することで今編集しているactivate()が実行されるのでデータベースに変更があった時だけdbDelta関数を呼び出しテーブルが追加更新されるようにするためです。

私たちのテーブルのバージョン番号は、WordPressの持つ設定を保存するテーブルに登録させてもらうことにしましょう。

独立した、名前の付いたデータ (「設定」) を WordPress データベースに保存し利用することができます。設定値の取り得る形式は、文字列 (string)、配列 (array)、もしくは PHP オブジェクトです (オブジェクトは、保管時は「シリアライズ」もしくは文字列に変換され、読出時にオブジェクトに戻されます)。オプション名は文字列で、他にない唯一のものでなければなりません。なぜなら、WordPress や他のプラグインと衝突しないためです(プラグインの作成を参照)。

使う関数は下の2つ、add_option()を利用する必要はありません。

update_option( $option, $new_value )

optionsデータベーステーブルから、指定したオプションの設定値を更新または作成します。オプションの設定値はインサートされる前に$wpdb->escapeでエスケープされます。また、指定された
オプション名が存在していないときにはadd_option( $option, $new_value )が実行されるので、add_option( $option, $new_value )の代りに使うことができます。

$option_name
    (文字列) (必須) 更新したい設定の名前。有効なデフォルトオプション値は、Option Referenceに一覧があります。

        初期値: なし

$newvalue

    (混合) (必須) 設定の新しい値。この値には、整数、文字列、配列やオブジェクトを取ることができます。

        初期値: なし
get_option( $show, $default )

optionsデータベーステーブルから、指定したオプションの値を取得する安全な方法です。希望するオプションが存在しない場合は、値が関連付けされず、FALSE が返されます。

 $show
    (文字列) (必須) 取得するオプションの名前。有効なデフォルトオプション値は、Option Referenceに一覧があります。

        初期値: なし

$default
    (混合) (オプション) 値が返されない(データベースにオプションが存在しない)場合のデフォルト値。

        初期値: false
完成したメソッド

SQL文は、別メソッドからの戻り値となるようにしました。

<?php
class CDPlugin {
    // 現在のテーブルのバージョン。
    // 数値を上げるとテーブルを更新する。
    // (テーブルが存在していて)上げなければ何もしない。
    private $version = 0.1;

    function __construct() {
    }

    public function activate() {
        $db_version = get_option('cdq_db_version', 0);

        $table_name = $wpdb->prefix . 'main_master';
        $is_db_exists = $wpdb->get_var($wpdb->prepare("SHOW TABLES LIKE %s", $table_name));

        if ($is_db_exists == $table_name && $db_version >= $this->version) {
            return;
        }

        require_once ABSPATH . "wp-admin/includes/upgrade.php";
        dbDelta($this->$getSql($table_name));

        update_option("cdp_db_version", $this->version);
    }

    private function getSql($table_name) {
        return <<<EOS
CREATE TABLE  $table_name (
     id mediumint(9) NOT NULL AUTO_INCREMENT,
     name tinytext NOT NULL,
     url VARCHAR(55) NOT NULL,
     created timestamp NOT NULL DEFAULT CURRENT_TIMESTAMP ON UPDATE CURRENT_TIMESTAMP COMMENT '作成日',
     modified timestamp NOT NULL DEFAULT '0000-00-00 00:00:00' COMMENT '修正日',
     UNIQUE KEY id (id)
);
EOS;
    }

}

複数のテーブルに対応

テーブルが1つだけなら良いのですが、複数のテーブルを使うプラグインでは、先のactivate()がテーブルの数だけ必要になります。そんな時はforeachで回したくなります。そのための工夫をしてみましょう。

テーブル名の識別とSQL文

先ず、テーブルを識別できるようにします。新しいテーブルを追加するときにここに追加記入します。

private $tables = array(
    "master_1",
    "detail_1",
    "master_2",
    "detail_2",
);

そしてもう一つ新しいテーブルを追加するときに記述しなければならないのはSQL文です。この二つを記述するだけで新しいテーブルを追加できるようにします。

それには、SQL文を返すメソッド名に規則を作ります。すなわちメソッド名に、上で記入したテーブルの識別を使って、例えば、こんな感じにします。

private function master_1Sql($table_name) {return "CREATE TABLE $table_name ・・・"}
private function detail_1Sql($table_name) {return "CREATE TABLE $table_name ・・・"}
private function master_2Sql($table_name) {return "CREATE TABLE $table_name ・・・"}
private function detail_2Sql($table_name) {return "CREATE TABLE $table_name ・・・"}

"テーブルの識別" . "Sql"がメソッド名になっています。新しいテーブルを追加するときに新たに記述するのはこれだけでそれ以外に修正する必要はありません。

プレフィックスをつける

実際にCREATEされるテーブル名(プレフィックスがつく)を作ります。

private function getTableNames() {
    global $wpdb;
    foreach ($this->tables as $name) {
        $this->table_names [$name] = $wpdb->prefix . $name;
    }
    return $table_names;
}
クエリを実行

そして、各テーブルごとにSQL文を発行し、クエリを実行するよう以下のコードをactivate()メソッドに埋め込みます。

require_once ABSPATH . "wp-admin/includes/upgrade.php";

$table_names = $this->getTableNames();
foreach ($table_names as $name => $table_name) {
     $sqlfunc = $name . "Sql";
    dbDelta($this->$sqlfunc ($table_name));
}

今回は、ここまで。

次回は、「$wpdb 編 その2」として、$wpdbの使い方、エラー処理(といっても、エラーメッセージを受け取るわけですが)などに触れたいと思います。

Ruby On Rails4 の開発を始められるまで その1

Ruby On Rails4 の開発を始められるまで その1

posted at 2014/01/14 by chikkun@コワーキングスペース町田

Ruby On Rails4の基本を、自分のメモも兼ねて、3回シリーズでご報告します。

今日はその第1回目(2回目はdeviseを使った認証機能の追加。3回目はRspecやCucumberを利用したテストの予定です)。

Railsを使って開発する直前までをまとめます。ただ一応、環境と目標とするのは以下のようです。OSの違いや、仮に同じOSでも微妙にバージョンで違ったりする場合もあるのでご注意下さい。

  1. OSはCentOS6.5とする(MarvericksにParallelsを利用して、SDカードにインストールしたもの—ほとんど何もインストールされていない)。
  2. アプリ名は「comachi」。
  3. Apache2+Passengerを利用し、標準で付いているWEBrickは利用しない。
  4. Railsは4とする。
  5. DBはPostgreSQLを利用する。
  6. 外見はTwitter Bootstrapを使用する。
rbenvのインストール

CentOS6ですとRubyが2系ではないので、まずはRuby2をインストールします。というのもRails4はRuby2を推奨しているからです。

ただ今後1.9等も必要になることが予想されるので、便利なrbenvを使ってRubyのバージョンを変えられるようにします。ただrbenvをインストールする前に、RubyやPassenger等で必要になりそうなものを事前にyumでインストールします。

$ yum -y install  yum-plugin-priorities zlib zlib-devel readline readline-devel openssl openssl-devel libxml2 libxml2-devel libxslt libxslt-devel httpd httpd-devel curl-devel bison gcc gcc-c++ git emacs
  • ※↑は1行です。
  • ※最後のemacsは、好みでvimなどでもw
  • ※上記のいくつかは、gitやapache、Passengerのインストールに必要なもの等も入っています。Passengerの場合は必要なものをインストール時に教えてくれるので、仮に足らなくても大丈夫です。
  • ※CentOSのバージョンによっては「–enablerepo=remi,epel」オプションを入れる必要があるかもしれません(6.5では必要はありませんでした)。

これで準備が出来たので、早速rbenvのインストールです。

# 必要に応じてsuなりsudoをして下さい
$ cd /usr/local
$ git clone git://github.com/sstephenson/rbenv.git rbenv
$ groupadd rbenv
$ chgrp -R rbenv rbenv
$ chmod -R g+rwxXs rbenv
$ cd rbenv
$ mkdir plugins
$ cd plugins
$ git clone git://github.com/sstephenson/ruby-build.git ruby-build
$ chgrp -R rbenv ruby-build
$ chmod -R g+rwxs ruby-build
環境変数の設定

rbenvのインストールは終わりましたが、環境変数を設定しないと使えません。

そこで環境変数を/etc/profileに設定します(「/etc/profile」を直接編集したくない場合は「/etc/profile.d/rbenv.sh」等に書くのも手です)。

$ emacs /etc/profile #viでも

で、一番下に以下のように環境変数を設定します。

export RBENV_ROOT="/usr/local/rbenv"
export PATH="$RBENV_ROOT/bin:$PATH"
eval "$(rbenv init -)"

これを書き込んで、それら環境変数を読み込みます。

$ source /etc/profile
Autoconfのバージョンアップ

最新のRuby2.2-devのインストールでは、autoconfのバージョンが低いと怒られるので、m4とAutoconfの上書きバージョンアップを行います。

$ wget ftp://ftp.gnu.org/gnu/m4/m4-1.4.17.tar.gz
$ tar xvzf m4-1.4.17.tar.gz
$ cd m4-1.4.17
$ ./configure --prefix=/usr
$ make
$ make install
$ cd ..
$ wget ftp://ftp.gnu.org/gnu/autoconf/autoconf-2.69.tar.gz
$ tar xvzf autoconf-2.69.tar.gz
$ cd autoconf-2.69
$ ./configure --prefix=/usr
$ make
$ make install
インストール可能なRubyの確認

インストール可能なRubyのパッケージを確認する。

$ rbenv install -l
...
  1.9.3-rc1
  2.0.0-dev
  2.0.0-p0
  2.0.0-p195
  2.0.0-p247
  2.0.0-p353
  2.0.0-preview1
  2.0.0-preview2
  2.0.0-rc1
  2.0.0-rc2
  2.1.0
  2.1.0-dev
  2.1.0-preview1
  2.1.0-preview2
  2.1.0-rc1
  2.2.0-dev
...

バージョンはお好みで。とりあえずここでは「2.2.0-dev」をインストールします。

$ rbenv install 2.2.0-dev #時間はそこそこかかります
$ rbenv rehash # これをやる必要があります
$ rbenv global 2.2.0-dev
インストールできたか確認
$ ruby -v
ruby 2.2.0dev (2014-01-12 trunk 44563) [x86_64-linux]

OKのようですw

PostgreSQLのインストール

yum.postgresql.orgに行って「pgdg-centos93-9.3-1.noarch.rpm」を持ってきて、rpmを実行します。

wget http://yum.postgresql.org/9.3/redhat/rhel-6-x86_64/pgdg-centos93-9.3-1.noarch.rpm
rpm -ivh pgdg-centos93-9.3-1.noarch.rpm

すなわち、wgetでダウンロードし、rpmでrepositoryのファイルをインストールします。そして次にyumでPostgreSQLをインストールします。

yum install -y postgresql93-server postgresql93-devel postgresql93-contrib

次にお決まりの「initdb」をし、サーバーを立ち上げます。またOSを再起動しても自動で立ち上げるためにchkconfigし、ついでにapacheも自動起動するようにします。

さらに、postgresユーザのパスワードを作成し、新しいユーザ(chikkun)、データベース(comachi)を作成します。

$ /etc/init.d/postgresql-9.3 initdb
$ /etc/init.d/postgresql-9.3 start
$ chkconfig --level 345 postgresql-9.3 on
$ chkconfig --level 345 httpd on
$ su postgres
$ psql
% alter role postgres with password 'hogehoge'; #postgresユーザにパスワードを設定
% \q
$ createuser -P -s chikkun
Enter password for new role: 
Enter it again:
createdb comachi
$ exit

それから、/var/lib/pgsql/9.3/data/pg_hba.confを少々書き換えます。

local   all             all                                     peer
# IPv4 local connections:
host    all             all             127.0.0.1/32            ident
# IPv6 local connections:
host    all             all             ::1/128                 ident

のpeer、identをmd5にします。

local   all             all                                     md5
# IPv4 local connections:
host    all             all             127.0.0.1/32            md5
# IPv6 local connections:
host    all             all             ::1/128                 md5

そして再起動。

/etc/init.d/postgresql-9.3 restart

たぶん、PostgreSQLのRuby用のモジュールでインストールで失敗するので、先にオプションを付けて、インストールしていまいます。

gem install pg -- --with-pg_config=/usr/pgsql-9.3/bin/pg_config
  • ※上の「–」が余計に見えますが、これがないと「そんなオプションはないよ」と言われます(というか、言われ続けました・涙)。
Railsのインストール

さてさて、何はなくともRailsをインストールします。

$ gem install rails
$ rbenv rehash
$ rails -v
Rails 4.0.2

どうやら大丈夫そう。

passengerのインストール

次に、gemを使ってpassengerをインストールします。

gem install passenger
passenger-install-apache2-module

先回りして、必要なものをインストールしているので全く同じ環境ならば大丈夫ですが、環境が違っていたりすると、足らないものが出たりします。

しかし、そのような場合は、以下のようなメッセージで、必要なもののリストをyumコマンド付きで教えてくれるので、インストールしたら再度「passenger-install-apache2-module」を実行します。

Installation instructions for required software

 * To install C++ compiler:
   Please install it with yum install gcc-c++

無事コンパイルが始まって、終了すると以下のようなメッセージが出ます。このうち、最初の頃のLoadModuleの部分と、最後の辺りにあるVirtualHostの部分が必要になります。

The Apache 2 module was successfully installed.

Please edit your Apache configuration file, and add these lines:

   LoadModule passenger_module /usr/local/rbenv/versions/2.2.0-dev/lib/ruby/gems/2.2.0/gems/passenger-4.0.33/buildout/apache2/mod_passenger.so
   PassengerRoot /usr/local/rbenv/versions/2.2.0-dev/lib/ruby/gems/2.2.0/gems/passenger-4.0.33
   PassengerDefaultRuby /usr/local/rbenv/versions/2.2.0-dev/bin/ruby

After you restart Apache, you are ready to deploy any number of web
applications on Apache, with a minimum amount of configuration!

Press ENTER to continue.


--------------------------------------------

Deploying a web application: an example

Suppose you have a web application in /somewhere. Add a virtual host to your
Apache configuration file and set its DocumentRoot to /somewhere/public:

   <VirtualHost *:80>
      ServerName www.yourhost.com
      # !!! Be sure to point DocumentRoot to 'public'!
      DocumentRoot /somewhere/public    
      <Directory /somewhere/public>
         # This relaxes Apache security settings.
         AllowOverride all
         # MultiViews must be turned off.
         Options -MultiViews
      </Directory>
   </VirtualHost>

And that's it! You may also want to check the Users Guide for security and
optimization tips, troubleshooting and other useful information:

  /usr/local/rbenv/versions/2.2.0-dev/lib/ruby/gems/2.2.0/gems/passenger-4.0.33/doc/Users guide Apache.html

http://www.modrails.com/documentation/Users%20guide%20Apache.html

Enjoy Phusion Passenger, a product of Phusion (www.phusion.nl) :-)

https://www.phusionpassenger.com

Phusion Passenger is a trademark of Hongli Lai & Ninh Bui.

すなわち

LoadModule passenger_module /usr/local/rbenv/versions/2.2.0-dev/lib/ruby/gems/2.2.0/gems/passenger-4.0.33/buildout/apache2/mod_passenger.so
PassengerRoot /usr/local/rbenv/versions/2.2.0-dev/lib/ruby/gems/2.2.0/gems/passenger-4.0.33
PassengerDefaultRuby /usr/local/rbenv/versions/2.2.0-dev/bin/ruby

<VirtualHost *:80>
   ServerName www.yourhost.com
   # !!! Be sure to point DocumentRoot to 'public'!
   DocumentRoot /somewhere/public    
   <Directory /somewhere/public>
      # This relaxes Apache security settings.
      AllowOverride all
      # MultiViews must be turned off.
      Options -MultiViews
   </Directory>
</VirtualHost>

が必要になります。もっと具体的には、上のものはそのままhttpd.confにコピペ、下のものは自分の環境に合わせて書き換えた後にhttpd.comfに追記します。

実際には私の場合以下のようにしました。

<VirtualHost *:80>
    ServerAdmin hoge@fuga.com
    DocumentRoot /var/www/html/rails/comachi/public
    ServerName www.comachi.com
    ErrorLog logs/comachi.error_log
    CustomLog logs/comachi.access_log common
    RackEnv development
    <Directory /var/www/html/rails/comachi/public>
        Options -MultiViews
        AllowOverride All
        Order allow,deny
        Allow from all
    </Directory>
</VirtualHost>

という感じです。

  • ※実際にの「DocumentRoot」は違っていて、CentOS自体がSDカードに入っていて、そのSDカード自体にRailsアプリを置いてあるので、実際には/media/psf/UBUNTU/rails/publicで「UBUNTU」はSDカードのボリューム名です。

そこで、/etc/httpd/conf/httpd.confのLoadModuleを記載している最後に(今回の例では217行あたり)上記の3行を追加します。

そして、VirutualHostの設定はhttpd.confの最後に(ディストリビューションによっては別ファイルのことも)上記のを参考に追記します。

ここではrailsのアプリの場所が「/var/www/html/rails/comachi」としていますが、適宜置き換えて下さい。また、Rails的にはdevelopmentにしてあります。

もう1つ。SELinuxが悪さしてApacheが立ち上がらないので(というか必要なことなんでしょうが、開発ではいらないので)「/etc/selinux/config」を

SELINUX=disabled

とし、これは再起動後もdisabledにするものなので、コマンドラインでも

setenforce 0

として、現在も無効にします。そして

$ /etc/init.d/httpd restart

します。

最後にVirtualHostを使っているので、「/etc/hosts」の最初の行のローカルホストの部分に「www.comachi.com」を追記します。すなわち

127.0.0.1   localhost localhost.localdomain localhost4 localhost4.localdomain4 www.comachi.com

さてさてあとは、railsのアプリを作成するだけです。

comachiアプリを作成

とりあえず今回のアプリ名を「comachi」と名付け、まずは何はなくともrailsコマンドのnewを実行します(comachiを作成する親ディレクトリにcdしてから)。

cd /var/www/html/rails
$ rails new comachi -d postgresql -T

※-Tはunit testを作成しないオプションで、Rspec等を使う場合には必要ないので付けました。

DBはsqliteがデフォルトなので、「-d postgresql」を付けてPostgreSQLを利用するようにします。ここで「Javascriptライブラリがない云々」とか怒られます。「therbyracer」を入れないとダメで、後で必要になるかもしれない「execjs」も含めて、GemFileに以下の2行を書き込みます。

gem 'therubyracer', platforms: :ruby
gem 'execjs'

そして

bundle install

を実行します。

外見はTwitter Bootstrap

Twitter Bootstrapを使ってデザインするので、Gemfileに以下を書き込みます(と思ったですが、後にこれは利用するBootstrapが2で、それ以外にgemなどで3が簡単に使えるようにならないか探したのですが、結局良さげなのがないのと「stackoverflow」であっさり、「ダウンロードしてvendor/assetに置くだけなんだから、自分でやれ」みたいなのを見て、全くその通りと思い、この方法をやめます)。

gem "twitter-bootstrap-rails"
gem "less-rails"

なので、↑はless-railsだけ残して、まずはBootstrapのダウンロードに行って、最新版をダウンロードして、解凍すると、

dist/
    css/
        bootstrap-theme.css
        bootstrap-theme.min.css
        bootstrap.css
        bootstrap.min.css ※
    fonts/
        glyphicons-halflings-regular.eot
        glyphicons-halflings-regular.svg
        glyphicons-halflings-regular.ttf
        glyphicons-halflings-regular.woff
    js/
        bootstrap.js
        bootstrap.min.js ※

というようなファイルが出てくるので、↑の※のファイルを(必要に応じて、追加します)

vendor/
    assets:
        javascripts/
            bootstrap.min.js
        stylesheets/
            bootstrap.min.css

というように、コピーします(vendorでなくても、「app/assets」でも大丈夫です)。
そして「app/assets/stylesheets/application.css」に

*= require bootstrap.min

を書き加えます。

また「app/assets/javascripts/application.js」に

//= require bootstrap.min

を書き込みます。

これで終了wtwitter-bootstrap-railsは使わないので、

gem "less-rails"

そして、以下を実行。

bundle install
最後にconfig/database.ymlの編集

データベースのinitdb で、作成したユーザやデータベース名に併せて、今回はdevelopment環境なので以下のように書き換えます。

development:
  adapter: postgresql
  encoding: utf8
  database: comachi
  pool: 5
  username: chikkun
  password: hogehoge

これで、ブラウザで http://www.comachi.com で次のような画面が見られたらOKです。

ok

これで開発が始められそうですw

WordPressのプラグイン作成 第一回

WordPress のプラグイン作成 はじめの一歩

posted at 2014/01/12 by denpoya@コワーキングスペース町田

最初のお話はプラグインを作成するための準備段階として、

  1. WordPressに「これはプラグインですよ」と認めてもらい、
  2. プラグインを有効化したときに実行してもらいたいメソッドactivate()を作り、それをWordPressに実行してもらう

というところまでお話していきたいと思います。activate()は、関数として実行させても良いですし、クラスで定義されたメソッドであっても良いので、両方の場合を紹介します。

そして、次回のテーマとしては、このactivate()メソッドの役割として、プラグインに必要なデータベースのテーブルを作ってもらうことにします。

WordPressにプラグインとして認めてもらう

プラグインを配置するディレクトリとPHPファイルを作っていきます。

プラグインの名前

では、作りたい機能からプラグインの名前を決めましょう。すでにある他のプラグインと同じ名前にならないように気をつけます。ここでは、私たちの社名「株式会社 C & D」を使って、「CD Plugin」をプラグイン名とします。

プラグイン・ファイル

次は、選択したプラグイン名に由来する名前のPHPファイルを作ります。プラグインをインストールする人は複数のプラグインを利用することでしょう。そのような自分以外のプラグイン・ファイル名と同じファイル名を使うことはできません。また、プラグインのディレクトリ名も同様に重ならない唯一の名前にします。

wordpress
:
|-- wp-content
|   |-- plugins     <----- プラグインを配置するディレクトリ
|   |   |-- cd_plugin   <----- 私たちのプラグインのディレクトリ
|   |   |   |-- CDPlugin.php
|   |   |   |-- cd_plugin.php
|   |   |   |--images
|   |   |   |   `-- cd_image.jpg
|   |   |   |--css
|   |   |   |   `-- style.css
|   |   |   |--js
|   |   |   |   `-- jquery.js

その中にはプラグイン・ファイルだけでなくプラグインで利用するCSSファイル、JavaScriptファイルや画像ファイルなどを配置するディレクトリもあることでしょう。

標準プラグイン情報

WordPress にプラグインの存在を認識させ、プラグイン管理画面に表示させる「標準プラグイン情報」は、プラグインのメインになるPHPファイルの先頭に記述します。それを私たちのcd_plugin.phpとします。

<?php
/*
 Plugin Name: (プラグインの名前)
 Plugin URI: (プラグインの説明と更新を示すページの URI)
 Description: (プラグインの短い説明)
 Version: (プラグインのバージョン番号。例: 1.0)
 Author: (プラグイン作者の名前)
 Author URI: (プラグイン作者の URI)
 License: (ライセンス名の「スラッグ」 例: GPL2)
*/

先のディレクトリ構造にはPHPファイルを二つ置きました。cd_plugin.phpCDPlugin.phpです。これらのうちcd_plugin.phpの方に「標準プラグイン情報」を書いてみましょう。
CDPlugin.phpやその他のディレクトリなどはなくてかまいません。「標準プラグイン情報」を記述することで、WordPressにプラグインであることを認めてもらえます。

  • cd_plugin.php に「標準プラグイン情報」を下のように記述しました。
<?php
/*
 Plugin Name: CD plugin
 Plugin URI: http://www.nothing.pom/cd_plugin
 Description: WordPress 初めてのプラグイン
 Author: コワーキング・スペース町田「小町」
 Version: 0.1
 Author URI: http://www.nothing.pom
*/

そして、WordPressの管理者としてログインし管理者メニューの[プラグイン]をクリックすると

プラグインとして登録

このようにプラグインの仲間入りができます。

プラグインが有効化された時に実行させる関数を登録する

『▲▲をしたタイミングで、◎◎をしてもらう。』そのための仕組みをプラグインフックといいます。フックにはたくさんの種類が用意されているので適切なフックを探す必要があります。プラグイン API/アクションフック一覧 が役に立つかもしれません。

関数register_activation_hook($file, $function)

これは、プラグインを有効化したときに実行してもらいたい関数を登録する関数です。
引数は、次のように説明されています(上記リンク参照)。

引数
$file (string) (必須)
    wp-content/pluginsディレクトリにあるメインプラグインファイルへのパス。フルパスが有効です。
    初期値: なし
$function (callback) (必須)
    プラグインが有効化されたときに実行される関数。PHPにおける疑似的な型callbackとして許可されたものである必要があります。
    初期値: なし
使用例

phpファイル自身の中に実行したい関数を記述している、またはインクルードされている場合には

register_activation_hook( __FILE__, 'myplugin_activate' );

のように登録します。

ここで「__FILE__」は、自分自身のPHPファイルのパス名が定義されている定数です。

また、クラスを作りそのメソッドを実行させたい場合には、まずクラスファイルをインクルードしておき、newメソッドでインスタンスを作成します。そして実行させたいメソッドを次のように登録することができます。

require_once dirname(__FILE__) . DIRECTORY_SEPARATOR . "クラスファイル.php";
$clazz = new クラス名();

register_activation_hook(__FILE__, array($clazz, "クラスのactivateメソッド名"));

では、私たちの例で具体的に作っていきましょう。

  • CDPlugin.phpに以下のコードを記述します。
<?php
class CDPlugin {
    function __construct() {
    }

    public function activate() {
        echo "初めてのプラグイン"; <-- これはやってはいけない。怒られます。
    }
}
  • cd_plugin.php にコードを追加します。

CDPlugin.phpを読み込ませて、インスタンスを作ります。

<?php
/*
 Plugin Name: CD plugin
 Plugin URI: http://www.nothing.pom/cd_plugin
 Description: WordPress 初めてのプラグイン
 Author: コワーキング・スペース町田「小町」
 Version: 0.1
 Author URI: http://www.nothing.pom
*/

require_once dirname(__FILE__) . DIRECTORY_SEPARATOR . "CDPlugin.php";
$cdp = new CDPlugin();

register_activation_hook(__FILE__, array($cdp, "activate"));

array()を使ってクラスとそのメソッド名を指定することで、プラグインが有効化されたタイミングで"activate"メソッドを実行するフックが登録されます。

ただし、「有効化」をしてこれを実行させるとメッセージが出てWordPressに怒られます。

有効化をしたとき

今回はここまで。

次回は、activate()メソッドの中を編集していきます。目標は、プラグインに必要なデータベースのテーブルを作成することです。その際、機能のバージョンアップに伴うテーブルの変更にも気を配っていきたいと思います。