WordPress 3.0 と プラグインアクション・フィルターフックへのクロージャ渡し

3.0 開発中は全然気がつかなかったのですが、WordPress 3.0 からプラグインのアクション・フィルターフックにクロージャが渡せるようになりました。

クロージャが使えるのは PHP 5.3 からなのでみんなに使ってもらうプラグインなどではあまり使えませんが、5.3 と決まった環境でのテーマつくりなどの作業の場合は楽できるかもです 🙂

特に、Thematic などテーマフレームワークの functions.php で小さなフックをつくらなければいけない場合に威力を発揮しそうです。 ついでに 5.3 じゃなくても楽する方法も紹介します。

修正元の trac はこちらです。

#10493 (Allow closures as callbacks) – WordPress Trac

PHP 5.3 allows closures, which means we can replace this:

add_action('init', create_function('', '//do something'));

with this:

add_action('init', function() { // do something });

and it only requires two lines of extra code.

実はサンプル上の create_function を使うパターンは少し前からマイブームだったのでタイムリー。 こちらは PHP 5.3 じゃなくてもいけます。

でもって、これって何の話かというと…。

いつもの、the_content のフィルターをつかった、記事の頭に☆をつけるサンプルでご説明。

まず、以下のソースが一般的にかいたフィルタープラグインフックです。

// 普通のパターン
function add_star($content) {
    return "☆" . $content;
}
 
add_filter('the_content', 'add_star');

 

別にこれでいいわけなんですが、問題は add_star っていう関数。 こんな小さい関数に名前をいちいち考えるのも大変ですし、他とかぶってはいけないという制約もあります。 要は面倒であります。

ってことで、PHP では create_function というのを使うと匿名関数というのがつくれますので(名無しさんですね)これを利用すると…。

// 匿名関数(create_function)
add_filter('the_content'
    , create_function('$content', 'return "▲" . $content;'));

 

add_star をなくせました。 create_function でつくりだした匿名の関数をフックに渡してしまいます。 ちょいフックならこれで十分。 これは PHP 5.3 じゃなくても動きます。

でもちょっと問題がありまして、見ての通り関数の内容がただの文字列。 IDE サポートもうけられませんし、何より分かりづらい。 SQL をソースコードに直接書いているようながっかり感があります(笑)

というわけで PHP 5.3 から登場した、無名関数。 PHP マニュアル見ると匿名と無名で分けてみるみたいですね。

php 無名関数 – Manual

無名関数はクロージャとも呼ばれ、 関数名を指定せずに関数を作成できるようにするものです。 コールバック パラメータとして使う際に便利ですが、用途はそれにとどまりません。

どうなるかというと、

// 無名関数(PHP 5.3)
add_filter('the_content'
    , function($content) { return '△' . $content;});

 

やぁすっきりしました。 function() {} ということで名前なしで関数を定義して、直で add_filter に渡してしまいます。(これが WordPress 3.0 からサポートされました)

ここまでで十分便利ですが、調子に乗って「振る舞いを変えた」無名関数を the_content に登録してみます。

// 無名関数(エンクロージャ参照)
function enclosure($value) {
    $add = $value;
    return function($content) use($add) {
        return $add . $content;
    };
}
 
add_filter('the_content', enclosure('□'));
add_filter('the_content', enclosure('■'));
 

 

これは今までは class でやっていたことを、関数で実装する感じです。 PHP のクロージャは外側の変数を参照するのに use を使うようです。 🙂

さてさて、これらを全部テーマの functios.php いれるとこんな感じになります。

closure01

予定通り全部動いていますね。 🙂

最後に thematic テーマフレームワークで head 部に generator meta タグを復帰させるコードをサンプルに。

// 匿名関数版(create_function)
add_action('init', create_function('',
    "remove_filter(
        'the_generator'
        , 'thematic_remove_generators');"), 999);
 
// 無名関数版(PHP 5.3)
add_action('init', function() {
    remove_filter(
        'the_generator'
        , 'thematic_remove_generators');},999);
 

 

というわけで、小さいフックをかかねばならない場合は、是非是非(←3回目…

WordPress 3.0 と プラグインアクション・フィルターフックへのクロージャ渡し」への1件のフィードバック

  1. ピンバック: power source*

コメントを残す