Aperçu des attributs

(PHP 8)

Les attributs PHP fournissent des métadonnées structurées et lisibles par machine pour les classes, méthodes, fonctions, paramètres, propriétés et constantes. Ils peuvent être inspectés à l'exécution via l'API de réflexion, permettant un comportement dynamique sans modifier le code. Les attributs offrent un moyen déclaratif d'annoter le code avec des métadonnées.

Les attributs permettent de découpler l'implémentation d'une fonctionnalité de son utilisation. Alors que les interfaces définissent une structure en imposant des méthodes, les attributs fournissent des métadonnées sur plusieurs éléments, y compris les méthodes, fonctions, propriétés et constantes. Contrairement aux interfaces, qui imposent l'implémentation de méthodes, les attributs annotent le code sans en modifier la structure.

Les attributs peuvent compléter ou remplacer des méthodes d'interface optionnelles en fournissant des métadonnées plutôt qu'une structure imposée. Prenons une interface ActionHandler qui représente une opération dans une application. Certaines implémentations peuvent nécessiter une étape d'initialisation, tandis que d'autres non. Plutôt que d'obliger toutes les classes implémentant ActionHandler à définir une méthode setUp(), un attribut peut indiquer les besoins en initialisation. Cette approche augmente la flexibilité en permettant d'appliquer les attributs plusieurs fois si nécessaire.

Exemple #1 Implémentation de méthodes optionnelles d'une interface avec des attributs

<?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("Le fichier n'existe pas.");
}
}

#[
SetUp]
public function
targetDirectoryExists()
{
if (!
file_exists($this->targetDirectory)) {
mkdir($this->targetDirectory);
} elseif (!
is_dir($this->targetDirectory)) {
throw new
RuntimeException("Le répertoire cible $this->targetDirectory n'est pas un répertoire.");
}
}

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