Übersicht über die Attribute

(PHP 8)

Attribute bieten die Möglichkeit, strukturierte, maschinenlesbare Metadaten-Informationen über Deklarationen in den Code einfügen: Attribute können für Klassen, Methoden, Funktionen, Parameter, Eigenschaften und Klassenkonstanten verwendet werden. Die durch Attribute definierten Metadaten können dann zur Laufzeit mit Hilfe der Reflection-APIs inspiziert werden. Attribute können daher als eine direkt in den Code eingebettete Konfigurationssprache betrachtet werden.

Mit Attributen können die allgemeine Implementierung eines Merkmals und seine konkrete Verwendung in einer Anwendung voneinander getrennt werden. In gewisser Weise ist dies vergleichbar mit Schnittstellen und deren Implementierung. Während es aber bei Schnittstellen und deren Implementierung um Code geht, geht es bei Attributen um die Angabe zusätzlicher Informationen und Konfiguration. Schnittstellen können von Klassen implementiert werden, während Attribute auch für Methoden, Funktionen, Parameter, Eigenschaften und Klassenkonstanten deklariert werden können. Attribute sind daher flexibler als Schnittstellen.

Ein einfaches Beispiel dafür, wie Attribute verwendet werden können, wandelt eine Schnittstelle mit optionalen Methoden so um, dass Attribute verwendet werden. Nehmen wir dazu mal an, eine Schnittstelle ActionHandler stelle eine Operation in einer Anwendung dar, bei der einige Implementierungen eines Action-Handlers von allen Klassen, vorkonfiguriert werden müssen und andere nicht. Anstatt die ActionHandler implementieren, zu verlangen, eine setUp()-Methode zu implementieren, kann ein Attribut verwendet werden. Ein Vorteil dieses Ansatzes ist, dass das Attribut mehrfach verwendet werden kann.

Beispiel #1 Implementierung optionaler Methoden einer Schnittstelle mit Hilfe von Attributen

<?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("Die Datei existiert nicht");
}
}

#[
SetUp]
public function
targetDirectoryExists()
{
if (!
file_exists($this->targetDirectory)) {
mkdir($this->targetDirectory);
} elseif (!
is_dir($this->targetDirectory)) {
throw new
RuntimeException("Das Zielverzeichnis $this->targetDirectory ist kein Verzeichnis");
}
}

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