WordPress ウィジェット を作る

WordPress ウィジェット を作る

今回は、ウィジェットの作り方です。

ウィジェットはサイドバーに表示される小さめのプラグインといった感じですね。実際、ウィジェットもプラグインとして作るわけです。ウィジェットを作ってみてそれからプラグインに入るといろいろわかりやすいのではないかと思いました。

いつものようにWordPress CodexのWordPress ウィジェット APIなどを参考にさせていただいています。

ウィジェットはプラグインとして作る

ウィジェットはプラグインとして作ります。プラグインを作るには、プラグインメインファイルの冒頭にコメントとして次のような情報を書き込んでおけば良いのでした。

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

これを記述したファイルを含むディレクトリをwp-contents/plugins/配下に置くと、WordPressによってプラグインと認識されます。管理者としてログインし、プラグインメニューを開くと一覧の中にプラグインの名前とその情報が表示されていることでしょう。

そのプラグイン(ウィジェット)を有効化すれば、管理メニューの「外観」->「ウィジェット」の中にあなたのウィジェットを見つけることができます。

Widget作成

プラグインではなくウィジェットにするには、WordPressのWP_Widgetクラスを継承したPHPクラスを作ります。そうすることで簡単にウィジェットにすることができます。基本的には、4つのメソッドをオーバーライドするだけです。構成は次のようになります。

なお、後ほど見るように管理者がウィジェットのために設定する項目は、WordPressのデータベースに登録されます。

class CD_My_Widget extends WP_Widget {

          // constructor
          function CD_My_Widget() {
                    /* ... */
          }

          // widget form :ウィジェットの設定画面
          function form($instance) {
                    /* ... */
          }

          // widget update :データベースに登録する値の処理
          function update($new_instance, $old_instance) {
                    /* ... */
          }

          // widget display :ウィジェットとして表示する内容の記述
          function widget($args, $instance) {
                    /* ... */
          }
}

// register widget :
add_action('widgets_init',  function() {
        register_widget("CD_My_Widget"); // WP_Widget を継承したクラス名を登録
    }
);

add_actionの第一引数にフックとして「widgets_init」を指定することで、widgetの初期化の時に第二引数の「文字列で指定された」関数が(フックされたタイミングで)実行されます(引数は文字列であることに注意)。

上の例では、関数名を指定する第二引数に無名関数を定義しています。無名関数は変数へ代入できるのでこのような使い方ができます。

add_action('widgets_init',  function() { register_widget("CD_My_Widget"); });

は、下のものと同等です。

add_action('widgets_init',  'hoge');

function hoge() { register_widget("CD_My_Widget"); }

このようにして、フックのタイミングでregister_widget("…")関数が呼び出され、クラス名「CD_My_Widget」を登録します。

次に、ウィジェットの各メソッドを見ていきましょう。

  1. コンストラクタ: function CD_My_Widget() { // }
  2. 設定を登録する管理画面フォーム: function form($instance) { // }
  3. データベースに登録する値を処理する:function update($new_instance, $old_instance) { // }
  4. ウィジェットコンテンツを表示する: function widget($args, $instance) { // }
コンストラクタ

継承した親のコンストラクタを呼び出し、このウィジェットにはcd_widgetという名前を付けました。このウィジェットのクラス名はCD_My_Widgetなので、コンストラクタは、

    function CD_My_Widget() {
        parent::WP_Widget(false, $name = 'cd_widget');
    }

となります(これはphp4の書き方なのですね。php5風に__construct()としても大丈夫です)。

ここでは先ず、最低限の内容として「タイトル」と「テキスト」を入力し、登録、表示させるウィジェットを完成させることにします。その際、それぞれに‘title’‘text’という(自分で決めた)キーを用いています。

設定を登録する管理画面フォーム

管理画面でウィジェットをサイドバーにドラッグ&ドロップした場所で表示される設定画面です。

    function form($instance) {
        if( $instance) {
            $title = esc_attr($instance['title']);
            $text = esc_attr($instance['text']);
        } else {
            $title = '';
            $text = '';
        }
    ?>
        <p>
            <label for="<?php echo $this->get_field_id('title'); ?>">
                <?php _e('Title:'); ?>
            </label>
            <input class="widefat" id="<?php echo $this->get_field_id('title'); ?>"
                   name="<?php echo $this->get_field_name('title'); ?>"
                   type="text"
                   value="<?php echo $title; ?>" />
        </p>

        <p>
            <label for="<?php echo $this->get_field_id('text'); ?>">
                <?php _e('Text:'); ?>
            </label>
            <input class="widefat" id="<?php echo $this->get_field_id('text'); ?>"
                   name="<?php echo $this->get_field_name('text'); ?>"
                   type="text"
                   value="<?php echo $text; ?>" />
        </p>

    <?php
    }

既に登録されている値があれば、「< > & ” ‘ (小なり、大なり、アンパサンド、ダブルクォート、シングルクォート)」 文字参照をエンコードして表示しています。

データベースに登録する値を処理する
    function update($new_instance, $old_instance) {
        $instance = $old_instance;

        $instance['title'] = strip_tags($new_instance['title']);
        $instance['text'] = strip_tags($new_instance['text']);

        return $instance;
    }

新しく登録する値からHTMLタグを剥ぎ取りハッシュで返します。設定値は「wp_optionsテーブル」に1レコードとして登録されます。

ウィジェットコンテンツを表示する
    function widget($args, $instance) {
        extract( $args );
        $title = apply_filters('widget_title', $instance['title']);
        $text = $instance['text'];

        echo $before_widget;
        // ウィジェット本体を囲む
        echo '<div class="widget-text cd_my_widget_block">';

        // 「タイトル」の表示
        if ( $title ) {
            echo $before_title . $title . $after_title;
        }

        // 「テキスト」の表示
        if( $text ) {
            echo '<p class="cd_my_widget_text">'.$text.'</p>';
        }

        echo '</div>';
        echo $after_widget;
    }

タイトルとテキストを表示するだけですが、立派にウィジェットが完成しました。

ちなみに、さりげなく使われている$before_title$after_title$before_widget$after_widgetといった変数は、引数の$argsextractしてできた変数です。

CSSファイルを読み込む

スタイルシートで表現をカスタマイズしたいですね。

スタイルシートを読み込むには、

    wp_register_style('識別子', 'cssファイルへのパス', array('依存する他の識別子'), 'ヴァージョン番号');
    wp_enqueue_style('識別子');

この2つの関数で実現できます。まずはwp_register_style関数で登録だけしておいて、そのスタイルシートを使う場面でwp_enqueue_style関数で読み込ませる、という使い方ができます。

wp_register_style関数
    wp_register_style(  $handle, $src, $deps = array(), $ver = false, $media = 'all'  );

$handle … スタイルシートを登録する「識別子」。初期値: なし。

$src … このスタイルシートのファイル名(パス付き)。初期値: false 。

$deps … このスタイルシートが依存していて、これよりも先に読み込まれていなければならないスタイシートの「識別子」を配列で記述する。初期値: array() 。

$ver … このスタイルシートのヴァージョン番号。初期値: false 。

$media … どの種類のmediaに対するスタイルシートなのかを指定する。例: ‘all’, ‘screen’, ‘handheld’, ‘print’。 初期値: ‘all’ 。

wp_enqueue_style関数
    wp_enqueue_style( $handle, $src = false, $deps = array(), $ver = false, $media = 'all' )

引数は、wp_register_styleと全く同じです。ソースを読むとwp_enqueue_style関数だけで引数があればスタイルシートの登録と同時に読み込ませられることがわかりました。確かめてみたら

    wp_enqueue_style('cd_jp_calendar_style', plugins_url('', __FILE__) . '/cd_jp_calendar.css', array(), '201406');

とすることでスタイルシートを読み込ませることができました。

いつスタイルシートを読み込ませるか

使いもしないのにスタイルシートだけを読み込ませておくのは無駄です。どのタイミングで読み込ませるかを指定するのがadd_action関数のフックですね。

    add_action( 'admin_init', '実行するメソッド');
    add_action( 'admin_menu', '実行するメソッド');
    add_action( 'wp_enqueue_scripts', '実行するメソッド');

admin_initフックは、管理画面が表示される時一番初めに実行する関数を登録します。

admin_menuフックは、管理画面が表示される時メニューまたはサブメニューの表示のされ方を指定する関数を登録します。

wp_enqueue_scriptsフックは、コンテンツが表示される時に読み込ませるフックです。

ここではスタイルシートについてだけ述べていますが、javascriptファイルを読み込ませる時もほとんど同じです。wp_register_stylewp_register_scriptに、wp_enqueue_stylewp_enqueue_scriptに置き換えるだけです。

add_action('wp_enqueue_scripts', 'cd_enqueue_scripts');

function cd_enqueue_scripts() {
    wp_enqueue_style('cd_my_widget_style', plugins_url('', __FILE__) . '/cd_my_widget.css', array(), '201406');
}
Widget 完成形

クラスの内部も記述した全体です。

<?php
/*
  Plugin Name:    CD Test Widget
  Plugin URI:     http://www.co-machi.org/plugins/cd_my_widget/
  Description:     テストウィジェットです。
  Author:         Denn
  Author URI:     http://www.co-machi.org/
  Version:         201406
  License:        GPL2
 */

if (!class_exists('CD_My_Widget')) :
    require_once WP_PLUGIN_DIR . '/cd_my_widget/CD_Foge.php';

    class CD_My_Widget extends WP_Widget {

        // constructor
        function CD_My_Widget() {
            parent::WP_Widget(false, $name = 'cd_widget');
        }

        // widget form :ウィジェットの設定画面
        function form($instance) {
            if ($instance) {
                $title = esc_attr($instance['title']);
                $text = esc_attr($instance['text']);
            } else {
                $title = '';
                $text = '';
            }
            ?>
            <p>
                <label for="<?php echo $this->get_field_id('title'); ?>">
                    <?php _e('Title:'); ?>
                </label>
                <input class="widefat" id="<?php echo $this->get_field_id('title'); ?>"
                       name="<?php echo $this->get_field_name('title'); ?>"
                       type="text"
                       value="<?php echo $title; ?>" />
            </p>

            <p>
                <label for="<?php echo $this->get_field_id('text'); ?>">
                    <?php _e('Text:'); ?>
                </label>
                <input class="widefat" id="<?php echo $this->get_field_id('text'); ?>"
                       name="<?php echo $this->get_field_name('text'); ?>"
                       type="text"
                       value="<?php echo $text; ?>" />
            </p>

            <?php
        }

        // widget update :データベースに登録する値の処理
        function update($new_instance, $old_instance) {
            $instance = $old_instance;

            $instance['title'] = strip_tags($new_instance['title']);
            $instance['text'] = strip_tags($new_instance['text']);

            return $instance;
        }

        // widget display :ウィジェットとして表示する内容の記述
        function widget($args, $instance) {
            extract($args);
            $title = apply_filters('widget_title', $instance['title']);
            $text = $instance['text'];

            echo $before_widget;
            // ウィジェット本体を囲む
            echo '<div class="widget-text cd_my_widget_block">';

            // 「タイトル」の表示
            if ($title) {
                echo $before_title . $title . $after_title;
            }

            // 「テキスト」の表示
            if ($text) {
                echo '<p class="cd_my_widget_text">' . $text . '</p>';
            }

            echo '</div>';
            echo $after_widget;
        }
    }

    endif;

// register widget
add_action('widgets_init', function() {
    register_widget("CD_My_Widget");
});

// register stylesheet
add_action('wp_enqueue_scripts', 'cd_enqueue_scripts');

function cd_enqueue_scripts() {
    wp_register_style('cd_my_widget_style', plugins_url('', __FILE__) . '/cd_my_widget.css', array(), '201406');
    wp_enqueue_style('cd_my_widget_style');
}

今回のウィジェットでは必要ありませんでしたが、別ファイルで定義した関数やクラスを使うためにインクルードする一行も入れてあります。

    require_once WP_PLUGIN_DIR . '/cd_my_widget/CD_Foge.php';

以上、ウィジェットの作り方でした。

プラグインより簡単に作れそう、と思っていただけたらうれしいです。

WordPressのウィジェットで、祝祭日対応カレンダーを作ってみました

WordPressのウィジェットで、祝祭日対応カレンダーを作ってみました。

マウスをホバーさせていない状態

祝祭日は赤数字で表示し、マウスをホバーさせると祝日の名前が浮かび上がります。

マウスをホバーさせた状態

また、投稿があった月では、その月の投稿の一覧表示画面へのリンクを付け(「平成26年5月」のところ)、投稿があった日には、その日の投稿へのリンクをつけました(上図でbackgroundが黄色になっているところ)。これはWordPressデフォルトのカレンダーにある機能を真似ました。前の月、次の月への切り替えもできるようにしました。

管理者での、ウィジェット設定画面で出来ることは、

ウィジェット設定画面

  1. 年の表示を元号(明治・大正・昭和・平成)と西暦のどちらかに指定できる。デフォルトは西暦。
  2. 月の表示を「*月」(デフォルト)、「和暦(睦月、如月、……)」、「英語(January,February,……)」にできる。
  3. 今月の何ヶ月前から表示するかを指定できる。
  4. 今月の何ヶ月後までを表示するかを指定できる。
  5. 西暦何年のカレンダーを表示するかを指定できる。

という、思いつくままに機能をつけた、まったく手前勝手な仕様です。
このカレンダーの設定はウィジェットに使うものではないだろう、というご指摘は全くその通りですね。

画像で施している設定は、今月の6か月前から今月の1ヶ月後までのカレンダーを表示させるというものです。

その設定ではうるさすぎるので現在は、デフォルトの設定にしてあります。ちょうど右側あたりに見えているのではないかと思います。

というわけで(なにがだ?)、「WordPressのWidgetを作る」の予告編でした。

みなさんもウィジェット作りに挑戦してみませんか。

作り方は次回の投稿で説明する予定です。

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の使い方、エラー処理(といっても、エラーメッセージを受け取るわけですが)などに触れたいと思います。

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

Facebook「いいね!」の「コメント入力欄」のポップアップ

Facebook「いいね!」ボタンは、Facebook公式プラグインを使用していますが、使い方によってWordPressのページが壊されてしまっていました。

指摘してくださった方、ありがとうございます。

2013-11-18 追加

今日、Facebook プラグインの「Like Button」を再々度(何度やったかは忘れましたが)試してみました。

すると、選択できるボタン3種類のうち、
[standard] を選択すると、相変わらずiPhoneでの表示が崩れてしまいますが、
[button_count]と[box_count] の2つではiPhoneでの表示が(一時崩れはしますが)正常になることを確認しました。

(もしかしてバグだった?のを修正?)

プラグインでiPhoneにも対応できるのなら、下の記事は不要になりますね。

無事解決しましたので、お礼がてらブログとして記録しておくことにいたしました。

「いいね!」ボタンを押すと

「いいね!」ボタンを押すと

【問題点】

写真のように、右下にある[閉じる]ボタンがきちんと表示されていません。
設定によっては、ボタンが全く表示されないため閉じることができなくなってしまいます。

これは、固定ページや投稿ページの本文中に入れる「いいね!」ボタンを押すと、コメントを入力するポップアップが出てきますが、その横幅の問題です。

横幅をデフォルトのままにすると、iPhoneで見たときにページのデザインが崩れてしまいます(これは、TwitterBootstrapとの絡みもあります)。そのために、横幅を調節したのですが…

横幅が狭いと、「いいね!」ボタンを押すと出てくるコメント入力欄の右下にある[閉じる]ボタンが見えず、コメント入力欄が開きっぱなしになってしまいます(写真の状態)。

【解決方針】

コメント入力欄が出てこないようにする。そのためには、・・・

Facebook プラグインのコードバージョンには、HTML5、XFBML、IFRAME、URL といった種類があります。

これらのうち、コメント欄のポップアップが出てくるのは、
HTML5、XFBML
の二つでした(URL版は一瞬出てきて何故かすぐ消えました)。

IFRAME 版のプラグインを使えば、コメント欄のポップアップは出てきません。

【IFRAME 版のプラグインを選択する方法】

  1. Facebook プラグインの設定項目のうち「Like Button」を選択し、「Like Button Settings」のページへ行きます。
    Facebook [Like Button]
  2. 「Read more… 」と書いてあるリンク先へ飛びます。
    Facebook [readme]
  3. 「URL to Like」の欄に、いいねをしてもらいたいページのアドレスを記入して、レイアウトなどを決めたら、下にある[Get Code]ボタンをクリックします。
    Facebook[Get Code]
  4. 現れたポップアップ内の[IFRAME]ボタンを押します。
    Facebook[IFRAME]
  5. 表示されたコードをコピーして、「いいね!」ボタンを置きたいページの場所に、コードを貼り付けます。
    Facebook[Paste Code]

おわり。