El paquete PHP Macro ofrece inyección de dependencia de establecimiento basada en cierre (función anónima) al proporcionar un rasgo que se puede incluir en cualquier clase.
composer req aimeos/macro
Este paquete es para desarrolladores de aplicaciones, marcos y bibliotecas que desean permitir que sus usuarios personalicen el comportamiento de su código.
En aplicaciones, marcos o bibliotecas creadas para personalización, es necesario permitir sobrescribir la funcionalidad existente para poder personalizar su comportamiento. Aquí es donde las macros son muy útiles porque pueden agregar código personalizado mediante cierres.
Con el paquete PHP Macro, también puede permitir a los usuarios sobrescribir métodos en clases base sin obligar a sus usuarios a extender estas clases. El paquete PHP Macro NO utiliza reflejos ni otros trucos, solo métodos PHP puros .
Existen algunos pros y contras en comparación con la inyección de dependencia basada en clases:
Pro:
Estafa:
Por lo tanto, no es un reemplazo para la inyección de dependencia basada en clases, sino una adición liviana para pequeños puntos de extensión donde la inyección de dependencia completa usando clases que implementan interfaces es demasiado trabajo.
El resultado de los métodos existentes se puede modificar si el método original busca una macro existente y usa en su lugar su propia implementación:
// 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 ;
}
};
Ahora, puede agregar su macro orderNumber
personalizada que se usará en su lugar:
// user code
Order:: macro ( ' orderNumber ' , function ( string $ id ) {
return date ( ' Y ' ) . ' - ' . $ id ;
} );
( new Order )-> getOrderNumber (); // now returns '2020-123'
Por lo tanto, puede generar su propia salida o pasar un resultado diferente a métodos posteriores dentro de la aplicación.
Cuando se llaman macros en el contexto de un objeto, también pueden acceder a las propiedades de la clase:
// original code
class A
{
use Aimeos Macro Macroable;
private $ name = ' A ' ;
};
Aquí, la propiedad privada $name
está disponible en la macro:
// user code
A:: macro ( ' concat ' , function ( array $ values ) {
return $ this -> name . ' : ' . implode ( ' - ' , $ values );
} );
( new A )-> concat ( [ ' 1 ' , ' 2 ' , ' 3 ' ] ); // returns 'A:1-2-3'
La macro puede usar la propiedad como entrada para crear el valor devuelto.
El paquete de macros PHP también permite heredar macros de las clases principales. Luego, pueden acceder a las propiedades de clase de la clase secundaria como si fueran métodos de clase normales:
// original code
class A
{
use Aimeos Macro Macroable;
private $ name = ' A ' ;
};
class B extends A
{
private $ name = ' B ' ;
};
Las macros agregadas a la clase principal también estarán disponibles en las clases secundarias:
// user code
A:: macro ( ' concat ' , function ( array $ values ) {
return $ this -> name . ' : ' . implode ( ' - ' , $ values );
} );
( new B )-> concat ( [ ' 1 ' , ' 2 ' , ' 3 ' ] ); // returns 'B:1-2-3'
La clase B
se extiende desde la clase A
pero proporciona una propiedad $name
diferente. La macro heredada de la clase A
ahora usará la propiedad de la clase B
También es posible sobrescribir macros heredadas de las clases principales, como es posible con los métodos de clase regulares:
// 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 {};
Ahora puede agregar macros a la clase principal y a una de las clases secundarias:
// 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'
Esto le permite agregar un manejo especial para clases individuales incluso si todas las demás clases todavía usan la macro agregada a la clase A
Las clases base suelen ofrecer un conjunto de métodos que utilizan las clases secundarias. En PHP, reemplazar los métodos de una clase base es imposible y, por lo tanto, debe sobrescribir cada clase secundaria con su propia implementación.
Para evitar eso, el método original puede usar el método call()
en lugar de llamar directamente al método de la clase principal:
// 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- ' );
}
};
Esto comprobará si hay una macro getName
disponible y la llamará en lugar del método 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'
El método getName()
original todavía se puede utilizar en la macro.
A veces, puede ser necesario eliminar macros de objetos, especialmente cuando se ejecutan pruebas automatizadas. Puede desarmar una macro usando:
class A
{
use Aimeos Macro Macroable;
};
// add macro
A:: macro ( ' test ' , function () {
return ' test ' ;
} );
// remove macro
A:: unmacro ( ' test ' );