PHP マクロ パッケージは、任意のクラスに含めることができる特性を提供することにより、クロージャ (匿名関数) ベースのセッター依存関係注入を提供します。
composer req aimeos/macro
このパッケージは、ユーザーによるコードの動作のカスタマイズを許可したいアプリケーション、フレームワーク、ライブラリの開発者向けです。
カスタマイズ用に構築されたアプリケーション、フレームワーク、またはライブラリでは、動作をカスタマイズできるように既存の機能を上書きできるようにする必要があります。この場合、クロージャを使用してカスタム コードを追加できるマクロが非常に便利です。
PHP マクロ パッケージを使用すると、ユーザーに基本クラスの拡張を強制せずに、基本クラスのメソッドを上書きできるようにすることもできます。 PHP マクロ パッケージは、リフレクションやその他のハックを使用せず、純粋な PHP メソッドのみを使用します。
クラスベースの依存性注入と比較すると、いくつかの長所と短所があります。
プロ:
短所:
したがって、これはクラスベースの依存関係注入の代替ではなく、インターフェイスを実装するクラスを使用した本格的な依存関係注入が多大な作業となる小規模な拡張ポイントのための軽量の追加です。
元のメソッドが既存のマクロをチェックし、代わりにそれを独自の実装で使用する場合、既存のメソッドの結果を変更できます。
// original code
class Order
{
use Aimeos Macro Macroable;
private $ id = ' 123 ' ;
public function getOrderNumber ()
{
$ fcn = static :: macro ( ' orderNumber ' );
return $ fcn ? $ fcn ( $ this -> id ) : $ this -> id ;
}
};
ここで、代わりに使用されるカスタムorderNumber
マクロを追加できます。
// user code
Order:: macro ( ' orderNumber ' , function ( string $ id ) {
return date ( ' Y ' ) . ' - ' . $ id ;
} );
( new Order )-> getOrderNumber (); // now returns '2020-123'
したがって、独自の出力を生成したり、アプリケーション内の後続のメソッドに異なる結果を渡したりすることができます。
マクロがオブジェクト コンテキストで呼び出される場合、クラス プロパティにもアクセスできます。
// original code
class A
{
use Aimeos Macro Macroable;
private $ name = ' A ' ;
};
ここでは、プライベート プロパティ$name
マクロで利用可能です。
// user code
A:: macro ( ' concat ' , function ( array $ values ) {
return $ this -> name . ' : ' . implode ( ' - ' , $ values );
} );
( new A )-> concat ( [ ' 1 ' , ' 2 ' , ' 3 ' ] ); // returns 'A:1-2-3'
マクロは、戻り値を作成するための入力としてプロパティを使用できます。
PHP マクロ パッケージでは、親クラスからマクロを継承することもできます。その後、通常のクラス メソッドと同じように、子クラスのクラス プロパティにアクセスできます。
// original code
class A
{
use Aimeos Macro Macroable;
private $ name = ' A ' ;
};
class B extends A
{
private $ name = ' B ' ;
};
親クラスに追加されたマクロは、子クラスでも使用できます。
// user code
A:: macro ( ' concat ' , function ( array $ values ) {
return $ this -> name . ' : ' . implode ( ' - ' , $ values );
} );
( new B )-> concat ( [ ' 1 ' , ' 2 ' , ' 3 ' ] ); // returns 'B:1-2-3'
クラスB
クラスA
を拡張していますが、別の$name
プロパティを提供します。クラスA
から継承したマクロは、クラスB
のプロパティを使用するようになります。
通常のクラス メソッドと同様に、親クラスから継承したマクロを上書きすることもできます。
// original code
class A
{
use Aimeos Macro Macroable;
public function do () {
return static :: macro ( ' concat ' )( [ 1 , 2 , 3 ] );
}
};
class B extends A {};
class C extends A {};
これで、親クラスと子クラスの 1 つにマクロを追加できるようになりました。
// user code
A:: macro ( ' concat ' , function ( array $ values ) {
return implode ( ' , ' , $ values );
} );
C:: macro ( ' concat ' , function ( array $ values ) {
return implode ( ' - ' , $ values );
} );
( new B )-> do (); // returns '1,2,3'
( new C )-> do (); // returns '1-2-3'
これにより、クラスA
に追加されたマクロを他のすべてのクラスが依然として使用している場合でも、単一のクラスに特別な処理を追加できます。
基本クラスは、多くの場合、子クラスで使用されるメソッドのセットを提供します。 PHP では、基本クラスのメソッドを置き換えることは不可能であるため、各子クラスを独自の実装で上書きする必要があります。
これを避けるために、元のメソッドは親クラスのメソッドを直接呼び出す代わりにcall()
メソッドを使用できます。
// original code
class A
{
use Aimeos Macro Macroable;
protected function getName ( $ prefix )
{
return $ prefix . ' A ' ;
}
};
class B extends A
{
public function do ()
{
return $ this -> call ( ' getName ' , ' B- ' );
}
};
これは、利用可能なマクロgetName
があるかどうかを確認し、 getName()
メソッドの代わりにそれを呼び出します。
// user code
( new B )-> do (); // returns 'B-A'
A:: macro ( ' getName ' , function ( $ prefix ) {
return $ this -> getName ( $ prefix ) . ' -123 ' ;
} );
( new B )-> do (); // returns 'B-A-123'
元のgetName()
メソッドはマクロ内で引き続き使用できます。
場合によっては、特に自動テストを実行する場合、オブジェクトからマクロを削除する必要がある場合があります。以下を使用してマクロの設定を解除できます。
class A
{
use Aimeos Macro Macroable;
};
// add macro
A:: macro ( ' test ' , function () {
return ' test ' ;
} );
// remove macro
A:: unmacro ( ' test ' );