WordPress プラグインをつくるときにぼくが結構大変に思うのは、実は管理画面をつくること・・・。
なにげに自分のプラグインのソースを眺めると実ロジックより大きいこともあったりして笑ってしまいます。 というわけで、既存の管理画面のないプラグインにポンとつける用途を念頭に試しに(本当に試しに)フレームワーク的なものをかいてみました 🙂
といっても、PHP 的に厳しい部分もあったりしてごにゃごにゃしなきゃいけない部分もありであまり実用的ではなく、まぁまぁこんな作り方もできるよねって話でみてもらえたらと思います。 PHP 5 系専用です。
まずはサンプル。 なにかしら管理画面の持たない既存のプラグインがあることにします。(以下、ソラでかいているので間違っているかもなのでイメージで)
なんでもいいですがおなじみ the_content フィルターで何か追加する感じのやつにしてみましょう。
1: function addContent($content) {
2: $header = "ほげ";
3: $content = "<p>$header</p>" . $content;
4: return $content;
5: }
6: add_filter('the_content', 'addContent');
記事の頭に「ほげ」ってつけるプラグインです。。 まぁサンプルってことでごかんべんを。(笑 プラグインヘッダなどは省略です。
ここでは固定値「ほげ」を管理画面から設定できるようにしたいと思います。
とりあえず、こいつを「クラス」にします。 っていってもほぼ機械的な置き換えです。
可変にしたい部分をフィールド(メンバ)においているところと「コンストラクタ」で初期化しているところに注目してください。
1: class example {
2:
3: var $header;
4:
5: function __construct() {
6: $this->header = "ほげ";
7: }
8:
9: function addContent($content) {
10: $content = "<p>{$this->header}</p>" . $content;
11: return $content;
12: }
13:
14: }
15: $example = new example();
16: add_filter('the_content', array($example, 'addContent'));
$header 変数が外にいきフィールド(メンバ)になりました。
__construct は new ってやったとき(15行目)に勝手に動く特別なメソッドだと思ってください。(ちなみに PHP はコンストラクタもメソッド扱いらしい)
変数を初期化して、あとは WordPress からの the_content の呼び出しを待っているイメージのプログラムです。
さてここからが本題。
今回つくってみたフレームワークというのは DolphinPanel という名前のプログラムで、こいつをつかうとこの手のプラグインに管理画面をつけられます。 “Dolphin” にはなんら意味はないです。 たまたまエコーザドルフィンを思い出しただけです。。(古)
まずプラグインのあたまで、このプログラムを require してあげます(1行目)。 で、プラグインのクラスに dolphin のインターフェースを “implements” します。
まぁかくだけです。 🙂
1: require_once('dolphin-panel.php');
2:
3: class example implements Dolphinable {
4:
5: var $header;
6:
7: function __construct() {
8: $this->header = "ほげ";
9: }
10:
11: function addContent($content) {
12: $content = "<p>{$this->header}</p>" . $content;
13: return $content;
14: }
15:
16: }
17: $example = new example();
18: add_dolphin($example, 'example');
19: add_filter('the_content', array($example, 'addContent'));
implements Dolphinable したクラス(3行目)は Dolphin 管轄の WordPress 管理画面を持つことができます。 権利をもったクラスを add_dolphin します。(18行目)
さて Dolphinable であるためには 3つの管理画面に関する決められたメソッド(onActive、onBind、onDispose)が必要になります。 これを実装していきます。
といっても単純にテキストボックスをひとつつけて、値を保存したいだけなら onActive だけ実装すればいいです。 onBind には return true; 、onDispose は空実装してください。
1: require_once('dolphin-panel.php');
2:
3: class example implements Dolphinable {
4:
5: var $header;
6:
7: function __construct() {
8: $this->header = "ほげ";
9: }
10:
11: function addContent($content) {
12: $content = "<p>{$this->header}</p>" . $content;
13: return $content;
14: }
15:
16: function onActive(DolphinForm $form) {
17: $form->add(new DolphinTextBox('$header', 'ヘッダ'));
18: }
19:
20: function onBind(DolphinForm $form) {
21: return true;
22: }
23:
24: function onDispose() { }
25:
26: }
27: $example = new example();
28: add_dolphin($example, 'example');
29: add_filter('the_content', array($example, 'addContent'));
17行目が Dolphin のキモで、この書き方で変数(フィールド)と管理画面のテキストボックスを結びつけます。 HTML フォームとの値変換、変数へのバインドをこの記述だけでやってくれます。(配列渡すと複数テキストボックスがでてきたりします)
おしまい!。
なんだかここだけみると不思議かもしれませんが、このコードだけでめでたく管理画面がつきます。 簡単あるね。 もちろんプラグインはこの設定値で動きます。 🙂
一応、もうちょっといじるとユーザ対話などもできるようになっています。 追加処理を書くとこんな感じになります。
ここではサンプルだったので極力短くしていますが、onBind は値検査が必要な場合に実装するメソッドで、onDispose はプラグインが非活性になった場合に実装するメソッドです。 入力値に必須が入っていなかった場合のメッセージ出力や、プラグイン非活性時のデータベースからの削除などができます。
もうちょっと詳しいコメント付きサンプルと Dolphin のソースを JSeries の CVS にコミットしてあります。 気になる方は(いるのか?!)みてみてください。
http://sourceforge.jp/cvs/view/wppluginsj/dolphin-panel/
実は管理画面でつかえる HTML コンポーネントがまだテキストボックスとチェックボックスだけだったり実用にはほど遠いのですが、まぁプラグインのサービスクラスに管理画面の意識がなくなるのは楽かなと思います。 また、ここではサービスクラスにつけていますが、単純な VO のクラスに implements して、上に親のサービスクラスをつくってプラグインを実装するのもいいかもです。
さて、お気づきの方もいらっしゃると思いますが、requre している関係でフレームワークとかいいつつクラス名称がかぶったりして、そのままだと Dolphinable な管理画面をもつプラグインがひとつしか作れなかったり、、、 namespace 使おうと思っても PHP 5.3 からだったりけっこう八方ふさがりなところがあったりします。
一応コントローラ自体は、ひとつで複数の Dolphinable を扱えるようにしているので、myhack.php とかにいれればいいんですが、もうないし(笑) __autoload とかで気合いで最新を読むような制御も考えましたが、hackish すぎるのでやめました。。 運用対処ということで(笑)
あとあと、PHP 5.3 じゃないと private プロパティがこじあけられないので、プラグインのフィールドは public にしてください。。 まぁスコープつけなきゃよいです。(お察しの通りリフレクションを使って変数をバインドしています)
というわけで、いろいろあって途中何度か企画倒れにしようかと思ったのですが、まぁせっかくつくったので話のネタに。 たぶんバグってると思うので、実用よりプログラム的な動きだけ楽しんでもらえればと思います。 🙂