(PHP 8)
PHP-Attribute bieten strukturierte, maschinenlesbare Metadaten für Klassen, Methoden, Funktionen, Parameter, Eigenschaften und Konstanten. Sie können zur Laufzeit über die Reflection-API inspiziert werden und ermöglichen dynamisches Verhalten ohne Änderung des Codes. Attribute bieten eine deklarative Möglichkeit, den Code mit Metadaten zu kommentieren.
Attribute ermöglichen es, die Implementierung eines Merkmals von seiner Verwendung zu trennen. Während Schnittstellen die Struktur definieren, indem sie Methoden vorschreiben, liefern Attribute Metadaten über mehrere Elemente, einschließlich Methoden, Funktionen, Eigenschaften und Konstanten. Im Gegensatz zu Schnittstellen, die die Implementierung von Methoden vorschreiben, kommentieren Attribute den Code, ohne dessen Struktur zu verändern.
Attribute können optionale Schnittstellenmethoden ergänzen oder ersetzen,
indem sie Metadaten anstelle einer vorgeschriebenen Struktur bereitstellen.
Ein Beispiel könnte eine ActionHandler
-Schnittstelle
sein, die eine Operation in einer Anwendung repräsentiert. Einige
Implementierungen könnten einen Konfigurationsschritt erfordern, während
andere dies nicht tun.
Anstatt alle Klassen, die ActionHandler
implementieren,
zu zwingen, eine setUp()
-Methode zu definieren, kann ein
Attribut die Setup-Anforderungen spezifizieren. Dieser Ansatz erhöht die
Flexibilität, da Attribute bei Bedarf mehrfach verwendet werden können.
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);