Aperçu des attributs

(PHP 8)

Les attributs permettent d'ajouter des informations de métadonnées structurées et lisibles par la machine sur les déclarations dans le code: les classes, les méthodes, les fonctions, les paramètres, les propriétés et les constantes de classe peuvent être la cible d'un attribut. Les métadonnées définies par les attributs peuvent ensuite être inspectées au moment de l'exécution à l'aide de l'API de Réflexion. Les attributs peuvent donc être considérés comme un langage de configuration intégré directement dans le code.

Avec les attributs, il est possible de découpler la mise en œuvre générique d'une fonctionnalité et son utilisation concrète dans une application. D'une certaine manière, ils sont comparables aux interfaces et à leurs implémentations. Mais là où les interfaces et les implémentations portent sur le code, les attributs concernent l'annotation d'informations supplémentaires et la configuration. Les interfaces peuvent être implémentées par des classes, mais les attributs peuvent également être déclarés sur sur les méthodes, les fonctions, les paramètres, les propriétés et les constantes de classe. Ils sont donc plus flexibles que les interfaces.

Un exemple simple d'utilisation d'attributs consiste à convertir une interface qui a des méthodes optionnelles pour utiliser des attributs. Supposons qu'une interface ActionHandler représentant une opération dans une application où certaines implémentations d'un gestionnaire d'action nécessitent une configuration et d'autres non. Au lieu d'exiger que toutes les classes qui implémentent ActionHandler implémentent une méthode setUp(), un attribut peut être utilisé. L'un des avantages de cette approche est que nous pouvons utiliser l'attribut plusieurs fois.

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