PHP 巨集套件透過提供可以包含在任何類別中的特徵,提供基於閉包(匿名函數)的 setter 依賴注入。
composer req aimeos/macro
該軟體包適用於希望允許用戶自訂程式碼行為的應用程式、框架和庫開發人員。
在為定製而建置的應用程式、框架或程式庫中,有必要允許覆寫現有功能以便能夠自訂其行為。這就是巨集非常方便的地方,因為它們可以使用閉包來添加自訂程式碼。
使用 PHP 巨集包,您還可以允許使用者覆寫基底類別中的方法,而無需強制使用者擴充這些類別。 PHP 巨集套件不使用反射或其他 hack,僅使用純 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 {};
現在您可以將巨集新增至父類別和子類別之一:
// 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 ' );