(PHP 8)
Los atributos de PHP ofrecen metadatos estructurados y legibles por máquinas para clases, métodos, funciones, parámetros, propiedades y constantes. Pueden ser inspeccionados en tiempo de ejecución a través de la API de Reflection, lo que permite un comportamiento dinámico sin modificar el código. Los atributos proporcionan una forma declarativa de anotar el código con metadatos.
Los atributos permiten desacoplar la implementación de una funcionalidad de su uso. Mientras que las interfaces definen la estructura mediante la imposición de métodos, los atributos proporcionan metadatos en varios elementos, incluidos métodos, funciones, propiedades y constantes. A diferencia de las interfaces, que obligan a implementar métodos, los atributos anotan el código sin alterar su estructura.
Los atributos pueden complementar o reemplazar métodos opcionales de una interfaz al proporcionar metadatos en lugar de
una estructura impuesta. Considera una interfaz ActionHandler
que representa una
operación en una aplicación. Algunas implementaciones pueden necesitar un paso de configuración, mientras que otras no.
En lugar de obligar a todas las clases que implementan ActionHandler
a definir un
método setUp()
, un atributo puede indicar los requisitos de configuración. Este enfoque
aumenta la flexibilidad, permitiendo que los atributos se apliquen varias veces cuando sea necesario.
Ejemplo #1 Implementación de métodos opcionales de una interfaz mediante atributos
<?php
interface ActionHandler
{
public function execute();
}
#[Attribute]
class SetUp {}
class CopyFile implements ActionHandler
{
public string $fileName;
public string $targetDirectory;
#[SetUp]
public function fileExists()
{
if (!file_exists($this->fileName)) {
throw new RuntimeException("El archivo no existe");
}
}
#[SetUp]
public function targetDirectoryExists()
{
if (!file_exists($this->targetDirectory)) {
mkdir($this->targetDirectory);
} elseif (!is_dir($this->targetDirectory)) {
throw new RuntimeException("El directorio de destino $this->targetDirectory no es un directorio");
}
}
public function execute()
{
copy($this->fileName, $this->targetDirectory . '/' . basename($this->fileName));
}
}
function executeAction(ActionHandler $actionHandler)
{
$reflection = new ReflectionObject($actionHandler);
foreach ($reflection->getMethods() as $method) {
$attributes = $method->getAttributes(SetUp::class);
if (count($attributes) > 0) {
$methodName = $method->getName();
$actionHandler->$methodName();
}
}
$actionHandler->execute();
}
$copyAction = new CopyFile();
$copyAction->fileName = "/tmp/foo.jpg";
$copyAction->targetDirectory = "/home/user";
executeAction($copyAction);