PHP lernen – Schleifen (for, foreach, while)

Welcome back,

heute widmen wir uns dem Thema Schleifen, mit denen wir gewünschten Code und Aktionen wiederholt ausführen können. Es gibt mehrere Arten von Schleifen, ich zeige dir die 3 wichtigsten: for, foreach und while. Los geht’s!

Was sind Schleifen?

Mit Schleifen können wir bestimmte Codestücke mehrfach ausführen. Dabei kann vorher bekannt sein, wieviele Male die Schleife durchlaufen wird, es gibt aber auch Fälle, in denen das vorher nicht bekannt ist. Außerdem sind Schleifen eine fantastische Sache um über Arrays oder Objekte zu iterieren.

Iteration
Eine sog. Iteration bezeichnet einfach eine mehrfache Wiederholung oder Ausführung bestimmter Prozesse oder Aktionen.

Fangen wir an mit der …

for-Schleife

Die for-Schleife ist perfekt wenn wir im vornherein wissen, wie oft sie durchlaufen werden soll. Dem for Schlüsselwort folgen in Klammern dann 3 Anweisungen:

  1. Code der vor dem Ausführen der Schleife ausgeführt wird. Im Regelfall wird hier eine numerische Variable deklariert und ein Wert zugewiesen – das ist die sog. Zählervariable.
  2. An zweiter Stelle wird ein Ausdruck ausgewertet – immer wenn dieser WAHR ergibt, wird das Ausführen der Schleife forgesetzt.
  3. Am Ende wird noch eine Anweisung ausgeführt – standardmäßig zählt man hier die Zählervariable hoch (oder runter, je nachdem).

Getrennt werden die Anweisungen mit dem ;  Semikolon. Innerhalb der Schleife (umschlossen von geschweiften Klammern wie auch bei if) kann beliebiger Code stehen.

Lassen wir Code sprechen:

Und das ist schon die ganze Magie. Wir deklarieren $zaehler mit dem Wert 0. In der zweiten Anweisung legen wir die Bedingung fest die WAHR ergeben muss, damit die Schleife weiterläuft. Im dritten Schritt legen wir den Code fest, der nach jedem Schleifendurchlauf ausgeführt wird – in dem Fall inkrementieren wir die $zaehler Variable (also $zaehler immer plus 1).

Das bedeutet wir starten mit $zaehler = 0, die Bedingung prüft, ob $zaehler kleiner als 5 ist (ja, 0 ist natürlich kleiner als 5) und anschließend addieren wir 1 zu $zaehler. Im zweiten Durchlauf hat $zaehler dementsprechend den Wert 1, das ganze Spiel geht so lange weiter, bis $zaehler irgendwann eben nicht mehr kleiner als 5 ist. Anschließend wird die Schleife verlassen und der Code danach wird ausgeführt.

Daher siehst du auch die folgende Ausgabe:

Macht Sinn, weil wir bei 0 beginnen und der letzte Wert (nachdem wir in jedem Durchlauf 1 dazu zählen) der kleiner als 5 ist natürlich die Zahl 4 sein muss.

Gut zu wissen
Das Inkrementieren bezeichnet eine schrittweise Erhöhung einer Variable.
Im Gegenzug ist mit dem Dekrementieren die schrittweise Verminderung des Werts einer Variable gemeint.

Beispiel #2

Natürlich können wir die Zählervariable mit einem anderen Wert außer 0 beginnen lassen und nach jedem Durchlauf auch mit einem beliebigen Wert inkrementieren oder dekrementieren. Ebenso können wir auch die Bedingung ändern. In der Programmierung nimmt man für for-Schleifen normalerweise immer die Variable $i – das hat sich einfach so eingebürgert, wie das klassische Hallo-Welt-Beispiel oder Foobar. Deswegen machen wir das auch so.

Geben wir doch einfach mal das 3er-Einmaleins aus:

Die Zählervariable hat zu Anfangs den Wert 3. Wir erhöhen die Zählervariable nach jedem Schleifendurchlauf um den Wert 3, bis sie kleiner oder gleich 30 ist.
Wir erhalten folgende Ausgabe:

Beispiel #3

Wie ich schon sagte können die Bedingungen und Anweisungen angepasst werden. Lass mich dir noch ein paar Code-Beispiele hierzu zeigen:

Dabei wird das ausgegeben:

 

Stolperfallen

Du musst aufpassen, dass dir nicht ein logischer Fehler unterläuft und das Programm in einer Endlosschleife endet. Das kann passieren, wenn die Bedingung niemals erfüllt wird – die Konsequenz ist dass das Skript so lange läuft, bis die maximale Skript-Ausführungszeit (die in der php.ini angepasst werden kann – nicht wichtig momentan) erreicht ist.

Dieser Code endet auf jeden Fall in einer Endlosschleife:

Je nach Einstellung bekommst du eine Fehlermeldung (oder musst nachher in der Log-Datei nachschauen – dazu kommen wir in einem späteren Artikel) die so oder so ähnlich aussieht:

Fatal error: Maximum execution time of 30 seconds exceeded on line number 4

Bedeutet dass die maximale Skript-Ausführungszeit von 30 Sekunden überschritten wurde und daher das Skript abgebrochen ist – und wir sehen sogar in welcher Zeile des Codes der Fehler auftrat.

Beispiel #3

Noch ein paar letzte kurze Beispiele für die Verwendung der for-Schleife.

Schleife um Array-Einträge auszugeben:

Ausgabe:

Ok das funktioniert, ist wirklich saumäßig ätzender Code – mit der foreach-Schleife können wir wesentlich effizienter arbeiten wenn es um Arrays geht.

Noch ein Beispiel mit Strings:

Die Ausgabe:

Wir beginnen in der for-Schleife wieder bei 0 zu zählen, und das solange die Zählervariable kleiner ist als die Anzahl an Zeichen des Strings. Wieviele Zeichen ein String enthält, kannst du mit der Funktion strlen ermitteln. Du übergibst den String und erhältst als Rückgabewert die Länge der Zeichen.

while-Schleife

Die while-Schleife läuft solange wie eine Bedingung WAHR ist – eine Zählervariable gibt es dafür nicht. Nach dem while Schlüsselwort geben wir in Klammern die Bedingung an – im Anweisungsblock kommt dann in geschweiften Klammern der Code der in jedem Schleifendurchlauf ausgeführt werden soll.

Im nachfolgenden Code deklarieren wir eine Variable $zahl und geben ihr den Wert 0. Die while Schleife soll so lange laufen wie $zahl kleiner ist als 10.

Die Ausgabe:

Bis hierhin kennen wir das eigentlich schon. Anders ist nur, dass wir die Zählervariable außerhalb des while-Konstrukts deklarieren und wir innerhalb der Schleife entscheiden, in welcher Art und Weise sich dessen Wert ändert.

Hier ist die Gefahr einer Endlosschleife sogar noch ein bisschen höher. Was passiert wenn wir vergessen den Wert von $zahl im Anweisungsblock zu ändern kannst du dir sicher vorstellen …

Momentan gibt’s keine besseren Beispiele für die while-Schleife – wir kommen aber nochmal darauf zurück, wenn wir mit Streams, Handlern und Datenbanken arbeiten.

foreach-Schleife

Mit der foreach-Schleife können wir „iterierbare“ Datentypen durchlaufen, zum Beispiel Arrays oder Objekte. Es ist sehr wahrscheinlich dass dort wo du mit Arrays zu tun hast früher oder später eine foreach-Schleife ins Spiel kommt. Nach dem foreach Schlüsselwort geben wir in Klammern die Variable an gefolgt von as und dann einer Variable die in jedem Schleifendurchlauf den aktuellen Wert repräsentiert.

Im folgenden deklarieren wir ein Array mit einigen Werten und geben diese in der Schleife aus:

Wir kriegen diese Ausgabe:

Wir geben an welches Array durchlaufen werden soll ($Mitarbeiter) und die Variable die den Wert repräsentiert ($value).

Schlüssel und Wert anzeigen

Wir können zusätzlich zum Wert auch jeweils den aktuellen Array-Index darstellen:

Die Ausgabe:

In den meisten Fällen geben wir Schlüssel und Wert an.

foreach in verschachtelten Arrays

Meistens hat eine Firma ja mehr als einen Mitarbeiter. Dementsprechend erstellen wir also ein Array mit mehreren Personen und geben diese nacheinander aus (inkl. Jahres-Gehalt).

Die Ausgabe – sehr hübsch:

Dadurch dass wir in diesem Fall ein mehrdimensionales Array haben, hat $value in jedem Schleifendurchlauf ein Unter-Array als Wert. Würden wir Zugriff auf die Daten eines Mitarbeiters (nehmen wir spontan mal den ersten) haben wollen, müssten wir entsprechend so schreiben:

Eine schön formatierte Ausgabe mit print_r macht es noch besser deutlich:

gibt uns das hier aus:

Die Werte des Haupt-Arrays sind also numerisch indiziert, die Werte der Unter-Arrays hingegen assoziativ (mit Namen, also ’name‘, ‚abteilung‘ und ‚gehalt‘).

foreach-Schleife in einem Formular

Legen wir nochmal ein Mitarbeiter Array an und machen die festgelegten Daten dann quasi-editierbar in einem Formular. Für die Abteilungen gibt es ein separates Array, die jeweilige Abteilung referenzieren wir in dem Mitarbeiter-Array dann über den Index. Schauen wir mal:

Nicht erschrecken, ist ein bisschen viel. Gehen wir Stück für Stück durch was dort alles passiert:

  • Wir aktivieren die Fehlerausgabe – passt.
  • Wir deklarieren ein Array für die Abteilungen (theoretisch können wir uns die Angabe der Indexes sparen, weil PHP die Werte von Haus aus so nummerieren würde – aber so ist es gleich ersichtlich).
  • Danach deklarieren wir das Mitarbeiter-Array mit allen Mitarbeitern. Bei der Abteilung geben wir anstatt den Wert (z.B. „Verkauf“) nur den Index des eigentlichen Wertes aus dem Abteilungen-Array an (ich sag dir dann gleich was das soll).
  • Anschließend kommt der ganze HTML-Kram um die Seite aufzubauen. Darunter auch unser Formular.
  • Dort durchlaufen wir dann alle Mitarbeiter und legen Eingabefelder fest, um die Daten zu bearbeiten.
  • Bei dem Dropdown für die Abteilungen durchlaufen wir alle Werte des $Abteilungen Arrays.
    Wichtig: du siehst dass wir hier eine Schleife in einer anderen Schleife haben (eine sog. verschachtelte Schleife), deswegen müssen wir hier unbedingt drauf achten, für die Schlüssel- und Werte-Repräsentation andere Variablennamen zu verwenden als die, die wir in der ersten (äußeren) Schleife schon haben. Wenn wir in der inneren Schleife erneut die Variablennamen „$mKey“ und „$Mitarbeiter“ verwenden, überschreiben wir die ja – das wollen wir auf keinen Fall.
  • Wir checken in Zeile 92 ob der Index des aktuellen Schleifendurchlaufs (für $Abteilungen) gleich ist mit dem Wert „abteilung“ des aktuellen Mitarbeiters. Falls ja geben wir “ selected“ aus, das heißt der option-Tag ist der aktiv selektierte Eintrag im DropDown.
  • Danach noch der Submit Button und am Ende lediglich noch eine Ausgabe der übermittelten Formulardaten.

Vielleicht ist dir aufgefallen, dass wir in den Eingabefeldern (und Dropdowns) beim name-Attribut zwei eckige Klammern angegeben haben (Zeilen 80, 84 und 88). Das ist die Schreibweise, wenn wir unter demselben Namen mehrere Felder absenden möchten. Wie print_r nach Absenden des Formulars gut veranschaulicht, funktioniert das auch soweit.

Warum die Sache mit den getrennten Abteilungen?

Das ist eigentlich eine gute Frage. Theoretisch hätten wir für jeden Mitarbeiter beim Index „abteilung“ auch gleich die Abteilung reinschreiben können – haben wir ja im vorletzten Beispiel auch gemacht und es hat funktioniert. Was soll also der umständliche Mumpitz?

Nun, das hat schon einen Grund, und zwar simulieren diese beiden Arrays eine ganz stark vereinfachte „Datenbankstruktur“. Das heißt die Daten im Array sind für das Programm unsere „Datenquelle“. Und bei Datenbanken ist es üblich (und Best practice), Redundanzen zu vermeiden und Daten die öfter vorkommen zu konsolidieren und in eine separate Tabelle zu überführen, um später nur noch über deren ID in einer anderen Tabelle auf die Werte zu referenzieren. Theoretisch würden wir nach dem Absenden des Formulars die Benutzereingaben in einer Datenbank persistent speichern – auf unser Beispiel angepasst würde das bedeuten, dass die Änderungen dann fix in den Arrays gespeichert werden müssten (was natürlich nicht geht).
Wie auch immer du musst das jetzt noch nicht wissen, trotzdem möchte ich dich kurz an diesem Thema schnuppern lassen.

Beispiel für verschachtelte Schleifen

Wie eben schon gezeigt können wir Schleifen in Schleifen haben (beliebig viele). Nehmen wir zum Beispiel das Einmaleins für die Zahlen von 1 bis 10:

Wir erhalten folgende Ausgabe:

 

Überspringen und Abbrechen (continue und break)

Fast sind wir für heute fertig. Es gibt nur noch eine letzte Sache die ich dir unbedingt zeigen muss, und ich hab mir das aus gutem Grund für den Schluss aufgehoben, weil es ein Thema ist, das alle Arten von Schleifen betrifft. Die Rede ist von den Schlüsselwörtern continue und break – klingt irgendwie paradox. Trotzdem sind das zwei sinnvolle Dinge:

continue Anweisung

Das continue-Schlüsselwort können wir an jedem Platz innerhalb der Schleife verwenden. Diese Anweisung führt dazu, dass der aktuelle Schleifendurchlauf an dieser Stelle verlassen wird und mit dem nächsten Durchlauf forgefahren werden soll.

Nehmen wir ein Array mit Vornamen und durchlaufen das in einer Schleife. Dort legen wir fest dass wenn der Name mehr als 5 Buchstaben lang ist, dieser Name einfach übersprungen werden soll. Das heißt wir geben nur Vornamen aus, die 5 oder weniger Buchstaben haben. Und das sieht so aus:

Dementsprechend erhalten wir die Ausgabe mit den aussortierten Namen:

continue sagt der Schleife also einfach nur, dass an der Stelle der Durchlauf abgebrochen wird und der nächste anfangen soll.

break Anweisung

Das break-Schlüsselwort können wir ebenfalls an jedem Platz innerhalb der Schleife verwenden. Diese Anweisung führt dazu, dass die Schleife augenblicklich verlassen wird, wir springen also komplett raus und die Schleife ist beendet.

Verwenden wir als Beispiel fast den gleichen Code wie eben, nur mit break statt continue. Und ich habe nach der Array Deklaration noch ein shuffle hinzugefügt, somit sind die Werte im Array bei jedem Seitenaufruf zufällig angeordnet (shuffle ordnet alle Werte im Array einfach zufällig an). Abermals gehen wir alle Namen in der Schleife durch, diesmal mit dem Unterschied dass wir die Schleife mit break sofort verlassen sobald der Name mehr als 5 Buchstaben gefunden hat.
Mach dir keine Sorgen beim Testen, es kann vorkommen dass du bloß eine leere weiße Seite im Browser angezeigt bekommst. Das liegt dann einfach nur daran dass zufällig grad ein Name mit mehr als 5 Buchstaben der erste in der Liste ist – Seite neuladen und gut ist.

Also dann:

Ich hatte jetzt z.B. die Ausgabe

Bei dir kommt wahrscheinlich wieder was anderes dabei raus.

Fazit

Bei der Programmierung wirst du um Schleifen nicht rum kommen, schon gar nicht wenn du später mit Datenbanken arbeitest. Der Einsatz von Schleifen ist vielfältig und je nach Anforderung kannst du entscheiden, welche Schleife gerade die optimale Lösung ist.

Im nächsten Artikel zeige ich dir, wie du Zufallszahlen generieren kannst – ebenfalls essentiell, denn Zufallszahlen (random numbers) gibt es in nahezu allen Programmiersprachen.

Gruß
Link

Kommentar hinterlassen

Deine E-Mail-Adresse wird nicht veröffentlicht. Erforderliche Felder sind mit * markiert.

* Die Checkbox für die Zustimmung zur Speicherung ist nach DSGVO zwingend.

Ich stimme zu.