PHP 매크로 패키지는 모든 클래스에 포함될 수 있는 특성을 제공하여 클로저(익명 함수) 기반 setter 종속성 주입을 제공합니다.
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 {};
이제 상위 클래스와 하위 클래스 중 하나에 매크로를 추가할 수 있습니다.
// 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 ' );