Descripción general de atributos

(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);