Einleitung: Zwei Lager, ein Kampf
\n\nJeder PHP-Entwickler steht früher oder später vor der Wahl: im funktionalen Stil programmieren oder in die Welt der Klassen und Objekte eintauchen. Es ist wie die Wahl zwischen einem Schweizer Taschenmesser und einem Multitool – beide Werkzeuge lösen Aufgaben, aber auf unterschiedliche Weise. In diesem Artikel beleuchten wir den funktionalen vs. objektorientierten Ansatz in PHP, sehen uns echten Code an und entscheiden, wann welches Werkzeug das richtige ist.
\n\nPHP ist eine einzigartige Sprache. Sie wurde als prozedurale Sprache geboren, wuchs zur OOP heran und nimmt in den neuesten Versionen (7.4+, 8.x) aktiv funktionale Features auf: Pfeilfunktionen, Closures, Typisierung. Das bedeutet, Sie können Ansätze mischen. Aber wie vermeidet man Verwirrung? Lassen Sie es uns herausfinden.
\n\nGrundlagen: Was die beiden Welten unterscheidet
\n\nFunktionaler Ansatz (Functional Programming)
\n\nHier steht die Funktion im Mittelpunkt. Reine Funktionen ohne Seiteneffekte, die immer ein vorhersagbares Ergebnis liefern. Kein gemeinsamer Zustand, keine Mutation von Variablen. Daten werden wie am Fließband durchgereicht.
\n\n// Funktionaler Stil: einfach, vorhersagbar\n$numbers = [1, 2, 3, 4, 5];\n\n$result = array_map(\n fn($n) => $n * 2,\n array_filter($numbers, fn($n) => $n % 2 === 0)\n);\n\nprint_r($result); // [4, 8]\n\nBemerkt? Wir verändern das ursprüngliche Array nicht, wir verwenden keine Schleifen. Alles ist deklarativ: nimm die geraden, verdopple sie, gib sie aus. Das spart Zeit beim Debuggen – es gibt keine Seiteneffekte.
\n\nObjektorientierter Ansatz (OOP)
\n\nOOP baut auf Objekten auf – Entitäten, die Zustand und Verhalten speichern. Klassen kapseln Daten, Vererbung erweitert die Funktionalität, Polymorphie ermöglicht es, die Logik im laufenden Betrieb zu ändern.
\n\n// OOP-Stil: Struktur und Wiederverwendung\nclass NumberProcessor {\n private array $numbers;\n\n public function __construct(array $numbers) {\n $this->numbers = $numbers;\n }\n\n public function getEvens(): array {\n return array_filter($this->numbers, fn($n) => $n % 2 === 0);\n }\n\n public function multiplyBy(int $factor): self {\n $this->numbers = array_map(fn($n) => $n * $factor, $this->numbers);\n return $this;\n }\n\n public function getResult(): array {\n return $this->numbers;\n }\n}\n\n$processor = new NumberProcessor([1, 2, 3, 4, 5]);\n$result = $processor->getEvens()->multiplyBy(2)->getResult();\nprint_r($result); // [4, 8]\n\nHier haben wir ein Objekt erstellt, das den Zustand speichert. Methoden können verkettet werden. Vorteil: Wenn eine neue Operation hinzugefügt werden muss, wird einfach eine Methode in die Klasse geschrieben.
\n\nWann der funktionale Ansatz gewinnt
\n\n1. Datenverarbeitung ohne Seiteneffekte
\n\nStellen Sie sich vor, Sie schreiben einen Log-Parser oder einen Währungsumrechner. Daten fließen durch eine Pipeline: einlesen → filtern → umwandeln → speichern. Funktionen sind hier die ideale Wahl. Sie sind unabhängig vom externen Zustand und leicht zu testen.
\n\n2. Sammlungen und Arrays
\n\nPHP bietet leistungsstarke Funktionen für die Arbeit mit Arrays: array_map, array_filter, array_reduce. In Kombination mit Pfeilfunktionen (PHP 7.4+) wird der Code zur Poesie.
$users = [\n ['name' => 'Anna', 'age' => 25],\n ['name' => 'Boris', 'age' => 17],\n ['name' => 'Vika', 'age' => 30],\n];\n\n$adultNames = array_map(\n fn($user) => $user['name'],\n array_filter($users, fn($user) => $user['age'] >= 18)\n);\n\n// ['Anna', 'Vika']\n\nSauber, lesbar, ohne Klassen. Für einfache Transformationen die beste Wahl.
\n\n3. Testen ohne Mocks
\n\nFunktionen haben keinen Zustand, daher sind sie einfach zu testen. Es müssen keine komplexen Mocks oder Stubs erstellt werden. Einfach Daten übergeben – Ergebnis erhalten.
\n\nWann der objektorientierte Ansatz unverzichtbar ist
\n\n1. Komplexe Geschäftslogik mit Zustand
\n\n