Upload
others
View
7
Download
0
Embed Size (px)
Citation preview
Jan Teriete
Objektorientiertes PHP7Grundlagen der objektorientierten Programmierung
Ein Webmasters Press Lernbuch
Version 11.1.2 vom 16.07.2020
Autorisiertes Curriculum für das Webmasters Europe Ausbildungs- und Zertifizierungsprogramm
— www.webmasters-europe.org —
Inhaltsverzeichnis10Einführung
10Einleitung
10Was sind Entwurfsmuster?
11Vorkenntnisse
11Aufbau der Lektionen
11Aufgaben im Fließtext
11»Testen Sie Ihr Wissen!«
12»Übungen«
12»Optionale Übungen«
12Anforderungen an PHP
13Strukturierung von PHP-Webprojekten
13Das Problem
13Strukturierung von PHP-Code
13PHP und HTML trennen
17Lesbaren Code schreiben
17Kapselung in Funktionen
19Funktionen, die atomare Probleme lösen
21Zusammenfassung
21Testen Sie Ihr Wissen!
22Einführung in die objektorientierte Programmierung
22Einleitung
22Was sind Objekte?
24Objekte in PHP
25Klassen
27Attribute
27Attribute verändern
28Attribute auslesen
28Attribute in Klassen definieren
30Methoden
30Grundlagen
31Vorteil von Methoden
32Die Variable $this
34Testen Sie Ihr Wissen!
35Übungen
36Getter- und Setter-Methoden
36Das Problem
36Kapselung
36Getter-Methoden
37Vorteil von Getter-Methoden
38Ein Attribut »protected« machen
40Setter-Methoden
40Nachteile des direkten Änderns eines Attributs
40Methoden zum Ändern von Attributen
42Öffentliche und geschützte Methoden
1
1.1
1.2
1.3
1.4
1.4.1
1.4.2
1.4.3
1.4.4
1.5
2
2.1
2.2
2.2.1
2.2.2
2.2.3
2.2.4
2.3
2.4
3
3.1
3.2
3.2.1
3.2.2
3.3
3.3.1
3.3.2
3.3.3
3.4
3.4.1
3.4.2
3.4.3
3.5
3.6
4
4.1
4.2
4.3
4.3.1
4.3.2
4.4
4.4.1
4.4.2
4.5
42Testen Sie Ihr Wissen!
43Übungen
44Arbeiten mit Objekten
44Das Problem
44Methoden, die andere Methoden aufrufen
46Methoden in anderen Objekten aufrufen
46Grundlagen
48Der instanceof-Operator
49Typdeklarationen
51Testen Sie Ihr Wissen!
52Übungen
53Virtuelle Attribute
53Das Problem
53Virtuelle Attribute
53Konzept
54Setter für virtuelle Attribute
55Testen Sie Ihr Wissen!
55Übungen
56Optionale Übungen
57Magische Methoden
57Das Problem
58Magische Methoden
58Konzept
58Die Methode __toString()
60Konstruktoren
60Konzept
60Die Methode __construct()
60Parameter an __construct() übergeben
62Ein assoziatives Array an den Konstruktor übergeben
66Testen Sie Ihr Wissen!
66Übungen
67Optionale Übungen
68Beziehungen zwischen Objekten
68Das Problem
68Objekte in anderen Objekten verstecken
70Ganze Objekte als Parameter übergeben
72Testen Sie Ihr Wissen!
72Übungen
73Optionale Übungen
74Vererbung
74Vererbung
75Horizontal Reuse
76Testen Sie Ihr Wissen!
4.6
4.7
5
5.1
5.2
5.3
5.3.1
5.3.2
5.3.3
5.4
5.5
6
6.1
6.2
6.2.1
6.2.2
6.3
6.4
6.5
7
7.1
7.2
7.2.1
7.2.2
7.3
7.3.1
7.3.2
7.3.3
7.3.4
7.4
7.5
7.6
8
8.1
8.2
8.3
8.4
8.5
8.6
9
9.1
9.2
9.3
77Objektrelationales Mapping
77Das Problem
77Verbreitete ORM-Entwurfsmuster
78Active Record
79Data Mapper
79Zusammenfassung
80Testen Sie Ihr Wissen!
81DateTime
81Einleitung
81Die DateTime-Klasse
82format
83modify
83diff
83Testen Sie Ihr Wissen!
84Autoloading & Namespaces
84Autoloading
85Namespaces
86Composer, Packagist & Co.
86Einleitung
86Composer-Einführung
86composer.phar
87Composer & Packagist
88composer.json
89Packagist
90Die eigentliche Installation
90Wichtige Composer-Dateien
90composer.lock
91autoload_namespaces.php
91Zusammenfassung
91Testen Sie Ihr Wissen!
92Anhang: Programmierrichtlinien
92Einleitung
92Richtlinien? Wieso? Weshalb? Warum?
93Hintergrund
93Die Empfehlungen
93PSR-1: Framework-Interoperabilität
94PSR-2: Stilistische Programmierrichtlinien
95Ergänzungen aus den Symfony-Standards
97Lösungen der Übungsaufgaben
99Lösungen der Wissensfragen
105Index
10
10.1
10.2
10.2.1
10.2.2
10.3
10.4
11
11.1
11.2
11.2.1
11.2.2
11.2.3
11.3
12
12.1
12.2
13
13.1
13.2
13.2.1
13.3
13.3.1
13.3.2
13.3.3
13.4
13.4.1
13.4.2
13.5
13.6
14
14.1
14.2
14.3
14.4
14.4.1
14.4.2
14.4.3
1.1
1.2
1 Einführung
In dieser Lektion lernen Sie
➤ welche Ziele diese Class hat.➤ was Entwurfsmuster sind.➤ was Sie an Wissen mitbringen sollten, um erfolgreich mit der Class arbeiten zu können.
Einleitung
Diese Class versucht, Ihnen eine neue Sichtweise auf die PHP-Programmierung zu vermitteln. Bisherhaben Sie wahrscheinlich vorwiegend kleinere Projekte mit PHP umgesetzt. Je größer ein Projekt aller-dings wird, desto wichtiger, aber auch schwieriger ist es, die Übersicht zu behalten. Ihnen die Fähigkei-ten dazu zu vermitteln, ist das Ziel dieser Class.
Natürlich werden Sie auch neue PHP-Techniken erlernen und werden in die Syntax der objektorientier-ten Programmierung eingeführt.
Im wichtigsten Teil dieser Class geht es darum, wie Sie die neuen und auch die bereits bekannten Tech-niken einsetzen können, um sauberen, wartbaren und vor allem lesbaren Code zu schreiben. WennSie diese Class durchgearbeitet haben, werden Sie nicht nur die Grundlagen der Objektorientierungbeherrschen, sondern werden Ihre OOP-Kenntnisse (objektorientierte Programmierung) auch einsetzenkönnen, um Code zu schreiben,
➤ den Sie auch nach Wochen und Monaten sofort wieder verstehen.
➤ der sich fast ein wenig so liest, wie Sie als Mensch sprechen würden.
➤ in dem Sie sofort, ohne groß zu suchen, die fragliche Codestelle finden.
➤ der Sie erfreulicherweise immer seltener überraschen wird (»Warum zum ...«).
Was sind Entwurfsmuster?
Ich versuche Ihnen, wie bereits erwähnt, in dieser Class zu vermitteln, wie Sie immer größer werdendePHP-Projekte wartbar und übersichtlich halten. Zu diesem Zweck werde ich auch auf Entwurfsmusterzu sprechen kommen. Entwurfsmuster oder englisch design patterns sind, kurz gesagt, eine praktischeMöglichkeit, von der Intelligenz und Erfahrung anderer Programmierer zu profitieren (siehe auchhttps://de.wikipedia.org/wiki/Entwurfsmuster).
Sie können sich sicher sein, dass jedes Programmierproblem, an dem Sie gerade knobeln, schon min-destens 100 Leute vor Ihnen gelöst haben. Viele dieser Probleme treten sogar so häufig auf, dass essich gelohnt hat, eine standardisierte Lösung zu entwerfen. So existieren inzwischen zu den gängigenProblemen der PHP-Programmierung fertige Vorgehensweisen, wie diese zu lösen sind. Diese Lösun-gen bestehen nicht aus fertigem Code, sondern versuchen nur den besten Weg zu zeigen, ein Problemanzugehen.
Daher nennt man sie Entwurfsmuster. Sie bieten eine Art Bauplan, nach dem Sie Ihren Code schreibenkönnen. Glauben Sie mir, es spart wirklich eine Menge Zeit und Nerven, wenn man Lösungsansätzekennt, die garantiert funktionieren, weil sie ständig verwendet werden.
10 1 Einführung
7.1
7Magische Methoden
In dieser Lektion lernen Sie
➤ was eine magische Methode ist.➤ wann die magischen Methoden __toString() und __construct() aktiviert werden.➤ was beim Aufruf von new eigentlich passiert.➤ wie Konstruktoren Ihnen das Erzeugen von Objekten erleichtern.
Das Problem
Je häufiger Sie mit Objekten arbeiten, desto mehr werden Sie feststellen, dass Sie bestimmte Dinge mitjedem Objekt einer Klasse anstellen. Jedes Mal, wenn Sie ein Person-Objekt erzeugen, rufen Sie danachdie Methoden setVorname() und setNachname() auf.
Beispiel
1 <?php<?php23 classclass PersonPerson4 {5 protectedprotected $vorname = '';6 protectedprotected $nachname = '';78 publicpublic functionfunction getVornamegetVorname()9 {
1010 returnreturn $this->vorname;11 }1213 publicpublic functionfunction getNachnamegetNachname()14 {15 returnreturn $this->nachname;16 }1718 publicpublic functionfunction setVornamesetVorname($vorname)19 {2020 $this->vorname = $vorname;21 }2223 publicpublic functionfunction setNachnamesetNachname($nachname)24 {25 $this->nachname = $nachname;26 }27 }
Codebeispiel 56 person.php
1 <?php<?php23 require_oncerequire_once 'person.php';45 $remolt = newnew PersonPerson();6 $remolt->setVorname('Marc');7 $remolt->setNachname('Remolt');89 var_dumpvar_dump($remolt);
Codebeispiel 57 neue_person.php (Version 1)
57
7.2
7.2.1
7.2.2
Gegen diese Schreibweise ist nichts einzuwenden, nur wäre es sinnvoll, wenn Dinge, die jedes Malbeim Erzeugen eines Objekts gemacht werden sollen, auch automatisch gemacht werden. Es ist einfachunnötig, drei Zeilen Code zu schreiben, wo theoretisch nur eine notwendig ist.
Magische Methoden
Konzept
Keine Sorge, wir driften jetzt nicht in die Esoterik ab. Eine magische Methode (engl.: magic method) isteine Methode, die Sie nicht aufrufen müssen, sondern die selbst weiß, wann sie gebraucht wird. Daherauch magisch - plötzlich tut sie etwas, ohne dass Sie es sagen mussten.
Diese Methoden haben einen festgelegten Namen und einen Auslöser. Wann immer dieser Auslöseraktiviert wird, sieht PHP nach, ob Sie die passende magische Methode definiert haben. Wenn ja, wirdsie ausgeführt. Einige mögliche Auslöser sind:
➤ Sie versuchen, ein Objekt mit echo auszugeben.
➤ Ein neues Objekt einer bestimmten Klasse wird angelegt.
➤ Sie versuchen, eine nicht existierende Methode aufzurufen.
➤ Sie versuchen, lesend auf ein nicht existierendes Attribut zuzugreifen.
Für eine komplette Liste aller magischen Methoden und ihrer Auslöser in PHP möchte ich Sie aufdie PHP-Referenz verweisen: http://php.net/de/language.oop5.magic.
Die Methode __toString()
Bevor wir uns an die Konstruktoren heranwagen, lassen Sie uns erst ein einfaches Beispiel für eine magi-sche Methode betrachten, nämlich __toString() . Was als Erstes auffällt, ist der seltsame Name, dermit zwei Unterstrichen (engl.: Underscore) beginnt. Das ist ein Kennzeichen für eine magische Methode:Jede beginnt mit zwei Unterstrichen __ .
Diese Methode wird immer dann aktiv, wenn Sie versuchen, ein Objekt mit echo auszugeben, was nor-malerweise fehlschlägt.
Beispiel
1 <?php<?php23 require_oncerequire_once 'person.php';45 $remolt = newnew PersonPerson();6 $remolt->setVorname('Marc');7 $remolt->setNachname('Remolt');89 echoecho $remolt; //Erzeugt einen Fehler
Codebeispiel 58 neue_person.php - Fehler (Version 2)
In Zeile 9 passiert genau das, was wir erwarten, es wird ein Fehler erzeugt. Es ist auch ziemlich abwegig,ein Objekt als Text ausgeben zu wollen. Wenn wir allerdings die magische Methode __toString() inder Klasse definieren, sieht die Sache ganz anders aus.
58 7 Magische Methoden
Beispiel
1 <?php<?php23 classclass PersonPerson4 {5 protectedprotected $vorname = '';6 protectedprotected $nachname = '';78 publicpublic functionfunction __toString__toString()9 {
1010 returnreturn $this->getVorname() . ' ' . $this->getNachname();11 }1213 publicpublic functionfunction getVornamegetVorname()14 {15 returnreturn $this->vorname;16 }1718 publicpublic functionfunction getNachnamegetNachname()19 {2020 returnreturn $this->nachname;21 }2223 publicpublic functionfunction setVornamesetVorname($vorname)24 {25 $this->vorname = $vorname;26 }2728 publicpublic functionfunction setNachnamesetNachname($nachname)29 {3030 $this->nachname = $nachname;31 }32 }
Codebeispiel 59 person_to_string.php
1 <?php<?php23 require_oncerequire_once 'person_to_string.php';45 $remolt = newnew PersonPerson();6 $remolt->setVorname('Marc');7 $remolt->setNachname('Remolt');89 echoecho $remolt; //Gibt "Marc Remolt" aus
Codebeispiel 60 neue_person.php (Version 2b)
Sobald das Objekt $remolt im Zusammenhang mit echo aufgerufen wird, ruft PHP die Methode__toString() auf und verwendet den Rückgabewert an der Stelle im Code als Text.
Sie können die Methode __toString() also verwenden, um eine für Menschen lesbare Repräsenta-tion des Objekts zu erhalten. Meistens nutzt man ohnehin eine derartige Methode, und so erhält mannoch den Magie-Bonus.
Sie müssen allerdings beachten, dass __toString() immer einen String zurückgeben muss. ImGrunde ist das zwar logisch, es wird aber leider immer wieder vergessen.
7.2 Magische Methoden 59
7.3
7.3.1
7.3.2
7.3.3
Konstruktoren
Konzept
Als Konstruktor bezeichnet man eine spezielle Methode, die beim Erzeugen eines Objekts aufgerufenwird. In ihr sollten Sie alles abarbeiten, was zur Verwendung des Objekts notwendig ist. Möglichkeitengibt es hier viele, daher nur ein paar Beispiele:
➤ Es werden Standardwerte für die Attribute gesetzt.
➤ Die Attribute werden auf Basis von Formulardaten befüllt.
➤ Das Objekt benötigt andere Objekte zum Betrieb. Diese werden im Konstruktor erzeugt.
Die Methode __construct()
Der Konstruktor könnte im Prinzip eine beliebige Methode sein, die Sie sofort aufrufen, nachdem Sieein Objekt mit new erzeugt haben. Dieser Weg hat allerdings zwei Nachteile:
➤ Sie benötigen zwei Zeilen Code.
➤ Sie könnten den Methoden-Aufruf vergessen.
Es ist besser, sich die Arbeit von PHP abnehmen zu lassen. Wenn Sie Ihren Konstruktor __construct()nennen, wird diese Methode automatisch beim Aufruf von new ausgeführt.
Beispiel
1 <?php<?php23 classclass TestKlasseTestKlasse4 {5 publicpublic $text;67 publicpublic functionfunction __construct__construct()8 {9 $this->text = 'Hallo Welt';
1010 }11 }1213 $test = newnew TestKlasseTestKlasse();14 echoecho $test->text; //Gibt "Hallo Welt" aus
Codebeispiel 61 test.php (Version 1)
Wann immer Sie also ein neues Objekt aus der Klasse TestKlasse erzeugen, wird das Attribut $textmit einem festen String befüllt. Das mag kein sonderlich sinnvolles Beispiel sein, aber es zeigt das Kon-zept.
Parameter an __construct() übergeben
Wie aber können Sie schon beim Erzeugen des Objekts Werte übergeben? Sie könnten einer Personschon beim Erzeugen einen Namen geben oder einen variablen Text in unserem vorherigen Beispielnutzen.
Das zu erreichen ist nicht schwer, und Sie erfahren auch endlich, warum Sie an den Klassennamen beimAufruf von new immer Klammern anhängen, als ob Sie eine Methode aufrufen würden. Die Antwortmüssten Sie inzwischen schon kennen: Zwar rufen nicht Sie eine Methode auf, aber PHP tut es, nämlich__construct() .
60 7 Magische Methoden
Alles, was Sie als Parameter in die Klammern hinter dem Klassennamen schreiben, landet direkt als Para-meter in der magischen Methode.
Beispiel
1 <?php<?php23 classclass TestKlasseTestKlasse4 {5 publicpublic $text;67 publicpublic functionfunction __construct__construct()8 {9 $this->text = 'Hallo Welt';
1010 }11 }1213 $test = newnew TestKlasseTestKlasse('Hallo Leute!');14 echoecho $test->text; //Gibt immer noch "Hallo Welt" aus
Codebeispiel 62 test.php (Version 2)
Der Code in Zeile 13 führt dazu, dass in dem Objekt $test die Methode __construct() mit demString 'Hallo Leute!' als Parameter aufgerufen wird, also genauso, als hätten Sie $test->__construct('Hallo Leute!') von Hand aufgerufen. Letzteres ist technisch gesehen übrigensdurchaus möglich, aber normalerweise durch den an einen Auslöser gebundenen automatisierten Auf-ruf unnötig. Durch den Aufruf ändert sich im Moment jedoch noch nichts im Objekt, da die Methodenoch keine Parameter erwartet.
Beispiel
1 <?php<?php23 classclass TestKlasseTestKlasse4 {5 protectedprotected $text;67 publicpublic functionfunction __construct__construct($eingabe)8 {9 $this->setText($eingabe);
1010 }1112 publicpublic functionfunction setTextsetText($text)13 {14 $this->text = $text;15 }1617 publicpublic functionfunction getTextgetText()18 {19 returnreturn $this->text;2020 }21 }2223 $test = newnew TestKlasseTestKlasse('Hallo Welt');24 echoecho $test->getTextgetText(); //Gibt "Hallo Welt" aus2526 $test = newnew TestKlasseTestKlasse('Wie geht es euch denn so?');27 echoecho $test->getTextgetText(); //Gibt "Wie geht es euch denn so?" aus
Codebeispiel 63 test.php (Version 2b)
Jetzt wird der String in der Methode __construct() im Attribut $text abgelegt und kann wiegewohnt weiterverarbeitet werden. Nebenbei haben wir auch noch den Code überarbeitet, indem wireinen passenden Getter und Setter geschrieben haben.
7.3 Konstruktoren 61
7.3.4
Lassen Sie uns nun das Problem vom Beginn dieser Lektion erneut aufgreifen. Der Aufruf könnte nunfolgendermaßen aussehen:
Beispiel
1 <?php<?php23 require_oncerequire_once 'person_konstruktor.php';45 $remolt = newnew PersonPerson('Marc', 'Remolt');67 echoecho $remolt; //Gibt "Marc Remolt" aus
Codebeispiel 64 neue_person.php (Version 3)
Natürlich müssen Sie noch die Klasse Person um einen Konstruktor erweitern, der den Vornamen undden Nachnamen als Parameter akzeptiert. Es ist also nicht wirklich eine Zeile, aber zumindest sehen Sienur noch eine.
Ein assoziatives Array an den Konstruktor übergeben
Wenn Sie dem Konstruktor viele Werte übergeben müssen, bietet es sich an, dies als assoziatives Arrayzu tun. So müssen Sie nicht auf die Reihenfolge der Parameter achten oder können das Array auch vor-befüllen und dem Konstruktor als eine Variable übergeben.
Im Konstruktor weisen Sie dann die einzelnen Werte aus dem Array den Attributen des Objekts zu,indem Sie deren Setter verwenden.
Beispiel
1 <?php<?php23 classclass PersonPerson4 {5 protectedprotected $vorname = '';6 protectedprotected $nachname = '';78 publicpublic functionfunction __construct__construct(arrayarray $daten = [])9 {
1010 ifif ($daten) {11 $this->setVorname($daten['vorname']);12 $this->setNachname($daten['nachname']);13 }14 }1516 publicpublic functionfunction __toString__toString()17 {18 returnreturn $this->getVorname() . ' ' . $this->getNachname();19 }202021 publicpublic functionfunction getVornamegetVorname()22 {23 returnreturn $this->vorname;24 }2526 publicpublic functionfunction setVornamesetVorname($vorname)27 {28 $this->vorname = $vorname;29 }303031 publicpublic functionfunction getNachnamegetNachname()32 {33 returnreturn $this->nachname;
62 7 Magische Methoden
34 }3536 publicpublic functionfunction setNachnamesetNachname($nachname)37 {38 $this->nachname = $nachname;39 }4040 }
Codebeispiel 65 person_konstruktor_array.php
1 <?php<?php23 require_oncerequire_once 'person_konstruktor_array.php';45 $person = newnew PersonPerson(6 [7 'vorname' => 'Arthur',8 'nachname' => 'Dent',9 ]
1010 );1112 echoecho $person;
Codebeispiel 66 neue_person.php (Version 4)
Der Konstruktor erhält als optionalen Parameter ein Array $daten und prüft über den TypeHint, ob erauch tatsächlich ein Array erhält. Die Methode selbst prüft, ob das Array Daten enthält. Wenn ja, werdendie Setter der Attribute mit den passenden Schlüsseln des Arrays beliefert.
Ein weiterer Vorteil dieses Konstruktors ist übrigens, dass Sie ihn sehr gut zusammen mit Formularenverwenden können. Formulardaten liegen normalerweise in $_POST in Form eines assoziativen Arrays.Na, klingelt es schon? Mit einem derartig aufgebauten Konstruktor können Sie folgenden Code schrei-ben:
$person = new Person($_POST);
Das ist doch mal praktisch, oder?
Wir können die ganze Sache sogar noch ein wenig weiter treiben. Oftmals existiert ein namentlicherZusammenhang zwischen den Array-Schlüsseln, den Attributen der Klasse und den Settern. So gehörenzum Array-Schlüssel vorname das Attribut $vorname und der Setter setVorname .
Beispiel
1 <?php<?php23 classclass PersonPerson4 {5 protectedprotected $vorname = '';6 protectedprotected $nachname = '';78 publicpublic functionfunction __construct__construct(arrayarray $daten = [])9 {
1010 // wenn $daten nicht leer ist, rufe die passenden Setter auf11 ifif ($daten) {12 foreachforeach ($daten asas $k => $v) {13 $setterName = 'set' . ucfirstucfirst($k);14 // pruefe ob ein passender Setter existiert15 ifif (method_exists($this, $setterName)) {16 $this->$setterName($v); // Setteraufruf17 }18 }19 }
7.3 Konstruktoren 63
2020 }2122 // gekuerztes Beispiel ohne __toString und Getter/Setter23 }
Codebeispiel 67 person_konstruktor_schleife.php
Das Beispiel nutzt genau diesen namentlichen Zusammenhang, indem das Array $daten in einerforeach -Schleife durchlaufen wird. Von jedem Schlüssel $k wird der Anfangsbuchstabe in einenGroßbuchstaben umgewandelt ( ucfirst ) und davor der String set ergänzt. Aus dem Schlüsselvorname wird so also der Methodenname setVorname .
Mit der Funktion method_exists() können Sie prüfen, ob eine Methode mit einem bestimmtenNamen in einem Objekt existiert. In unserem Beispiel wird in Zeile 15 also bestätigt, dass es die MethodesetVorname in dem aktuellen Objekt gibt.
Handelt es sich um eine gültige Methode, so rufen wir diese in Zeile 16 auf und übergeben den Array-Wert $v als Parameter ( $this->$setterName($v) ). Hierfür nutzen wir das Konzept der Variablen-funktionen: Wenn Sie an das Ende einer Variablen Klammern hängen, versucht PHP eine Funktion auf-zurufen, deren Name der aktuelle Wert der Variablen ist. Dies gilt natürlich auch für die Methoden einesObjektes, wenn wir noch $this und den Pfeil-Operator davorschreiben.
Die Konstruktor-Methode durchläuft also das Array $daten , und wenn es einen Setter passend zumSchlüssel gibt, wird dieser aufgerufen. Schlüssel, zu denen es kein Attribut im Objekt gibt, werden ein-fach ignoriert.
Allerdings löst unser schöner neuer Konstruktor nicht alle Probleme. Häufig muss man ein existierendesObjekt aktualisieren.
Beispiel
1 <?php<?php23 require_oncerequire_once 'person_konstruktor_array.php';45 $person = newnew PersonPerson(6 [7 'vorname' => 'Marc',8 'nachname' => 'Remolt',9 ]
1010 );1112 //hier passieren viele Dinge ...1314 $formularDaten = [15 'vorname' => 'Jan',16 'nachname' => 'Teriete',17 ];1819 $person->setVorname($formularDaten['vorname']);2020 $person->setNachname($formularDaten['nachname']);2122 echoecho $person;
Codebeispiel 68 neue_person.php (Version 5)
Wie im Beispiel veranschaulicht, würde man für diese Aktualisierung weiterhin jeden Setter einzeln auf-rufen. Nicht wirklich schön, oder?
64 7 Magische Methoden
Übung 23:
1. Sie haben in dieser Lektion gelernt, wie Sie alle Setter aufrufen können, ohne dass Sie jedenAufruf einzeln notieren müssen. Überlegen Sie, wie das ging.
2. Probieren Sie es nun aus. Ist der entstandene Code lesbar?
Wenn Sie sich an den Abschnitt 7.3.3 zurückerinnern, so kennen Sie eine Schreibweise für den manuel-len Aufruf einer magischen Methode. In diesem Fall benötigen Sie den Konstruktor, der dann automa-tisch jeden Setter aufruft, zu dem ein Array-Schlüssel existiert.
Allerdings wäre Ihr Code nicht besonders gut lesbar, wenn Sie für eine Aktualisierung von Objekt-Datenjedesmal den Konstruktor aufrufen würden. Zudem besteht die Möglichkeit, dass der Konstruktor wei-tere Aufgaben neben dem Aufruf der Setter wahrnimmt. Doch wie lässt sich dieses Problem lösen?
Beispiel
1 <?php<?php23 classclass PersonPerson4 {5 protectedprotected $vorname = '';6 protectedprotected $nachname = '';78 publicpublic functionfunction __construct__construct(arrayarray $daten = [])9 {
1010 $this->setDaten($daten);11 }1213 publicpublic functionfunction setDatensetDaten(arrayarray $daten)14 {15 // wenn $daten nicht leer ist, rufe die passenden Setter auf16 ifif ($daten) {17 foreachforeach ($daten asas $k => $v) {18 $setterName = 'set' . ucfirstucfirst($k);19 // pruefe ob ein passender Setter existiert2020 ifif (method_exists($this, $setterName)) {21 $this->$setterName($v); // Setteraufruf22 }23 }24 }25 }2627 publicpublic functionfunction getVornamegetVorname()28 {29 returnreturn $this->vorname;3030 }3132 publicpublic functionfunction setVornamesetVorname($vorname)33 {34 $this->vorname = $vorname;35 }3637 publicpublic functionfunction getNachnamegetNachname()38 {39 returnreturn $this->nachname;4040 }4142 publicpublic functionfunction setNachnamesetNachname($nachname)
7.3 Konstruktoren 65
7.4
7.5
43 {44 $this->nachname = $nachname;45 }46 }
Codebeispiel 69 person_set_daten.php
Code, der eine klar definierte Aufgabe hat (z.B. Aufruf der Setter auf Basis des assoziativen Arrays),lässt sich normalerweise auslagern (Stichwort Single Responsibility Principle). In diesem Fall soll dieseFunktionalität fest an die Objekte der Person -Klasse gebunden sein, weswegen wir den Code in dieMethode setDaten() auslagern und diese im Konstruktor in Zeile 10 aufrufen. Wann immer Sie dieDaten eines bestehenden Objekts aktualisieren wollen, können Sie fortan diese Methode nutzen.
Testen Sie Ihr Wissen!
1. Welche Auslöser für magische Methoden gibt es in PHP?
Bitte ankreuzen:
2. Welche Aussagen über magische Methoden sind in PHP korrekt?
Bitte ankreuzen:
Übungen
Übung 24:
Erweitern Sie die Klasse Fussball aus den Aufgaben von Lektion 5, so dass sie über einen Kon-struktor verfügt, dem die Attribute des Fussballs direkt übergeben werden können. VerwendenSie mehrere Parameter. Erzeugen Sie mehrere Bälle und geben Sie deren Beschreibung mittelsbeschreibeFussball() aus.
Übung 25:
Ersetzen Sie die Methode beschreibeFussball() durch die magische Methode__toString() . Passen Sie auch die Ausgabe in der index.php an.
Sie versuchen, ein Objekt mit echo auszugeben.
Ein neues Objekt einer bestimmten Klasse wird instanziiert.
Sie versuchen, eine nicht existierende Methode aufzurufen.
Sie versuchen, lesend auf ein nicht existierendes Attribut zuzugreifen.
Die Methode __construct() ist eine magische Methode.
Die Methode __toString() ist eine magische Methode.
Die Methode __toString() lässt sich über nachfolgenden Code auch manuell aufrufen:
$blume = new Blume();$blume->__toString();
Virtuelle Attribute können nur über magische Methoden verändert werden.
66 7 Magische Methoden
7.6 Optionale Übungen
Übung 26:
Ändern Sie die Klasse Fussball und verwenden Sie nun einen einzelnen Parameter als Array.Erweitern Sie hierfür die Klasse um die Methode setDaten() .
7.6 Optionale Übungen 67