プラグイン開発でシングルトンパターンを使う

Tech

何番煎じの記事になるんだろうと思ってましたが、意外にも日本語の文献がないので書いてみます。

WordPressのプラグイン開発では、独自で定義する関数(hookのcallback等)をクラス化して隠匿することが良いとされています。
これは主に、WordPressのコアや他プラグインで同名の関数を使われていた場合に、関数名が衝突してしまう可能性に対しての回避策になります。

クラス化

例えば以下のような2つのプラグインが有効化されていた場合に、どのような問題が発生するかは容易に想像できるでしょう。

// PluginA
function get_hoge() {
	return '1';
}

// PluginB
function get_hoge() {
	return '2';
}

これを以下のようにクラスメソッドとして定義することで、クラス名がユニークであれば問題は発生しません。

// PluginA
class Plugin_A {
	function get_hoge() {
		return '1';
	}	
}

// PluginB
class Plugin_B {
	function get_hoge() {
		return '2';
	}
}

シングルトンパターン

シングルトンパターンは、クラスのインスタンス化を制限し、クラスのインスタンスが常に1つだけであることを保証するデザインパターンです。

WordPressのプラグイン開発においては、単一のプラグインに閉じた話であればインスタンスが単一であろうと複数であろうとあまり関係のない話ではありますが、プラグインで追加したhookをremoveするときにインスタンスを特定する必要があるため、1つであった方が都合が良いこともあります。

こういった側面からシングルトンパターンが好まれているようです。

実際にプラグインのコードをシングルトンで記述すると以下のようになります。

/**
 * Plugin Name: Singleton Plugin
 * Version:     1.0.0
 */

class Singleton_Plugin {

    private static $instance;

    public static function get_instance() {
        if ( is_null( self::$instance ) ) {
            self::$instance = new self();
        }
        return self::$_instance;
    }

    private function __construct() {
        add_action( 'init', array( $this, 'init' ) );
    }

    public function init() {
        // 処理
    }
}
Singleton_Plugin::get_instance();

initにhookされている関数をremoveしたい場合は、以下で出来ます。

remove_action( 'init', array( Singleton_Plugin::get_instance, 'init' ) );

まあ、正直 $_GLOBAL でも良いとは思いますが、どちらにせよインスタンスにアクセスできる余地を残しておいた方がユーザーにとって優しい設計だと思います。

シングルトンパターンの課題

このようにシングルトンパターンはWordPressのプラグイン開発と親和性があります。
ただ、シングルトンパターンにはそれ自体とWordPress特有のデメリットも存在しますので、次回はそのあたりの紹介をしていこうと思います。

タイトルとURLをコピーしました