1

私が取り組んできたマイクロフレームワークへのプラグインインターフェイスを構築しており、概念的な問題を解決しようとしています。私が作成することに決めた最初の「プラグイン」は、基本的に Stripe 用の PHP ライブラリを取得し、それをプラグインとしてラップする、Stripe 統合です。次のようなプラグイン インスタンスの取得を可能にする一種のファクトリ パターンがあります。

$stripe = Iceberg::getPlugin('Stripe');

クラスをインスタンス化できる場合は十分に単純ですが、Stripe ライブラリの場合、すべてのクラスはstaticです。彼らの例でinclude()は、メインの Stripe ファイルを実行することを推奨しており、次のように使用できます。

Stripe::setApiKey('xyz');

私の切断は、getPlugin()静的インターフェイスのみを公開するクラスでメソッドを機能させる方法です。クラスをインスタンス化して正しく動作することを期待できないことは明らかですが、同時に、インスタンスまたは静的オブジェクトに関係なく、このメソッドが動作することを望んでいます。

私が持っていた 1 つのアイデアは__call()、Stripe プラグイン クラスにメソッドを実装し、それらの呼び出しを Stripe ライブラリに静的に渡すことです。

プラグインを使用してコントローラーで

$stripe = Iceberg::getPlugin('Stripe');
$stripe->setApiKey('xyz');

プラグインで

public function __call( $name, $arguments ) 
{
    Stripe::$name($arguments);
}

そのようなものがうまくいくかどうかはわかりませんし、うまくいくとしても、それが最善の方法であるかどうかはわかりません.

TLDR:オブジェクト コンテキストと静的コンテキストの両方でクラスとやり取りできるオブジェクトを作成するにはどうすればよいですか?

4

1 に答える 1

2

__call引数を正しく転送する限り、転送は機能するはずです。

public function __call($name, $arguments) 
{
    return call_user_func_array(['Stripe', $name], $arguments);
}

一般に、プラグインはインスタンスベースのように見えますが、実際にはそうではないため、これは問題になる可能性があります (状態はstatic舞台裏にあるため、すべてのインスタンス間で共有されます)。Iceberg::getPluginあなたのケースでは、異なるプラグイン名ごとに毎回同じインスタンスを返すことがおそらく文書化されているため、実際には問題ではないかもしれません。

とは言うものの、ここでの問題は、Stripe ライブラリの作成者がライブラリを静的にするという初歩的な間違いを犯したという事実に起因しており、これはあらゆる種類の問題 (共有状態、単体テスト用のライブラリのモックが難しい) につながります。

同じ間違いをしないでください:からすべての public static メンバーを失いますIceberg。誰かがあなたのサービスに非常に便利にアクセスしたい場合は、いつでもこれを行うことができます:

function Iceberg() {
    static $instance;
    if ($instance === null) $instance = new Iceberg();
    return $instance;
}

彼らは以前Iceberg()->foo()と同じように書くことができるようになりIceberg::foo()、フレームワークの作成者として、非静的アーキテクチャの利点を享受して開発することができます。あなたの未来の自分とあなたのユーザーは、あなたに感謝します。

于 2013-10-30T13:20:26.237 に答える