Einleitung: Ein kleiner Buchstabe, der alles verändert
\n\nStellen Sie sich vor: Sie entwickeln ein cooles PHP-Framework oder einfach eine Bibliothek für Ihr Projekt. Alles läuft perfekt, aber einen Monat später stellen Sie fest, dass sich die Kindklassen nicht so verhalten, wie Sie es erwartet haben. Sie erstellen ein Objekt, und es gibt – zack! – eine Instanz der Elternklasse zurück. Kommt Ihnen bekannt vor? Willkommen im Club derer, die auf new self vs. new static gestoßen sind.
\n\nDiese Frage auf Stack Overflow hat tausende Aufrufe, und das zu Recht. Der Unterschied zwischen self und static in PHP ist nicht nur syntaktischer Zucker, sondern ein grundlegender Mechanismus, der Ihr Projekt retten oder in einen Wartungsalbtraum verwandeln kann. Im Jahr 2025, während PHP sich weiterentwickelt, ist das Verständnis von Late Static Binding eine Pflichtfähigkeit für jeden ernstzunehmenden Entwickler.
In diesem Artikel wiederholen wir nicht einfach die Dokumentation. Wir analysieren reale Anwendungsfälle, zeigen Anti-Patterns und geben klare Best Practices, die Sie noch heute anwenden können. Los geht's!
\n\nHauptteil: self vs. static – Der Kampf um den Kontext
\n\n1. self – Der konservative Compiler-Freund
\n\nDas Schlüsselwort self in PHP bezieht sich immer auf die Klasse, in der es geschrieben wurde. Denken Sie daran wie an einen alten, treuen Freund, der sich nie ändert. Wenn Sie new self() in einer Elternklasse schreiben, erstellt dieser Code immer ein Objekt genau dieser Elternklasse – selbst wenn er von einer Kindklasse aufgerufen wird.
<?php\nclass Animal {\n public static function create() {\n return new self(); // Immer Animal\n }\n}\n\nclass Dog extends Animal {\n // Erbt create()\n}\n\n$dog = Dog::create();\necho get_class($dog); // Gibt aus: Animal\n?>\n\nSehen Sie? Wir haben die Methode der Klasse Dog aufgerufen, aber ein Animal erhalten. Das ist oft eine Überraschung für Anfänger. Wo liegt der Haken? self wird bereits zur Kompilierzeit aufgelöst. PHP "versiegelt" den Verweis auf die Klasse, in der die Methode deklariert ist, und keine Vererbungsmagie kann das ändern.
2. static – Der revolutionäre Late Binder
\n\nstatic ist das genaue Gegenteil. Es wird zum Zeitpunkt des Methodenaufrufs ausgewertet und bestimmt, welche Klasse die Methode aufgerufen hat. Das ist das Late Static Binding, das seit PHP 5.3.0 existiert.
<?php\nclass Animal {\n public static function create() {\n return new static(); // Erstellt eine Instanz der Klasse, die die Methode aufgerufen hat\n }\n}\n\nclass Dog extends Animal {\n // Erbt create()\n}\n\n$dog = Dog::create();\necho get_class($dog); // Gibt aus: Dog\n?>\n\nWas für eine Wendung! Jetzt gibt Dog::create() einen Hund zurück, kein abstraktes Tier. static schaut, wer die Methode aufgerufen hat, und erstellt ein Objekt genau dieser Klasse. Das bietet eine unglaubliche Flexibilität beim Aufbau von Klassenhierarchien.
3. Wann self, wann static verwenden?
\n\nDie goldene Regel: Verwenden Sie self, wenn Sie eine feste Bindung an die aktuelle Klasse benötigen, und static, wenn Kindklassen das Verhalten überschreiben können sollen.
Hier sind einige konkrete Szenarien:
\n\nSzenario A: Factory-Methoden (Verwenden Sie static)
\nEin klassisches Beispiel ist das Factory Method-Entwurfsmuster. Sie möchten, dass jede Kindklasse sich selbst erstellt.
\n\n<?php\nabstract class Vehicle {\n abstract public function getType(): string;\n\n public static function create(): static {\n return new static();\n }\n}\n\nclass Car extends Vehicle {\n public function getType(): string {\n return 'Auto';\n }\n}\n\nclass Bike extends Vehicle {\n public function getType(): string {\n return 'Fahrrad';\n }\n}