Navigation
 Startseite
 Fachbücher
 Anzeigenmarkt
 Forum
 Webmaster News
 Script Newsletter
 Kontakt
 Script Installation
 Php
 Php Tutorials
 Webhoster Vergleich
 Impressum

Community-Bereich
 kostenlos Registrieren
 Anmelden
 Benutzerliste

Script Datenbank
 Script Archiv
 Script Top 20
 Screenshots
 Testberichte

Suche
 

Unsere Php Scripts
 Counter Script
 Umfrage Script
 Bilder Upload Script
 Terminverwaltung
 Simple PHP Forum
 RSS Grabber

Tools und Generatoren
 .htpasswd Generator
 md5 Generator
 base64 Generator
 Markdown to HTML
 Colorpicker
 Unix timestamp Tool
 Unit Test Generator
 TLD Liste
 Webkatalog‑Verzeichnis

Hosterplus.de
Bekommen Sie Speicherplatz (Webspace), Domains...
https://www.Hosterplus.de
Artfiles.de
Bietet Serviceorientierte...
https://www.Artfiles.de
 
 
 

foreach Schleife in Php

Sie befinden sich: Home > Php > foreach Schleife in Php

Das PHP-Sprachkonstrukt foreach stellt eine einfache und schnelle Lösung dar, wenn jedes Element eines Arrays überprüft oder verändert werden soll. Man spricht hierbei auch von einer Iteration. Eine foreach-Schleife kann ausschließlich auf Arrays und Objekte angewendet werden, eine Anwendung auf Integer oder Charakterstrings, oder allgemein anderen Variablen führt zu Fehlern. PHP stellt zwei Arten der foreach-Schleife zur Verfügung, wobei die zweite Variante etwas ungewöhnlicher, jedoch gelegentlich zum Einsatz kommt.

foreach (array as $wert)
Ausdruck (z. B. echo $wert;)

foreach (array as $key => $wert)
Ausdruck (z. B. echo $wert;)

Die erste Funktion schreibt bei jedem Durchlauf des Arrays das aktuelle Element in die Variable $wert, und inkrementiert (erhöhen um eins) den internen Zeiger auf das Array um eins, um auf das nächste Element zugreifen zu können.

Die zweite Variante der foreach-Schleife gleicht grundsätzlich der ersten, jedoch wird zusätzlich zum Feldinhalt auch der Feldname (Schlüssel) an die Variable $key übergeben. Dies ist dann sinnvoll, wenn es sich um ein Array mit assoziativen Feldindizes handel.

Der interne Zeiger auf das entsprechende Array wird beim Aufruf von foreach(); automatisch auf das erste Element gesetzen, so, dass ein zusätzlicher Aufruf von reset(); entfallen kann.

Seit PHP 7 arbeitet foreach sichekt auf dem Original-Array, wenn &$wert verwendet wird. Möchte man Werte im Array ändern, verwendet man die Referenz-Schreibweise (foreach ($array as &$wert)), wie im folgenden Beispiel gezeigt.

Das folgende Beispiel erläutert die grundlegende Funktionsweise:

<?php
$feld_eins = array(1, 2, 3, 4);
/**
* Das & Zeichen vor $wert muss verwendet
*  werden damit der Wert des Elements verändert
* werden kann.
**/

foreach ($feld_eins as &$wert) {
  $wert = $wert * 2;
}
/**
* $feld_eins hat nun folgenden Inhalt (2, 4, 6, 8)
**/

/**
* Ein weiteres Beispiel dieses Mal
* für ein zweidimensionales Array
**/
$feld_zwei = array();

/**
* eine für PHP ungewöhnliche
* Zuweisung für Felder eines Arrays
**/
$feld_zwei[0][0] = "a";
$feld_zwei[0][1] = "b";
$feld_zwei[1][0] = "y";
$feld_zwei[1][1] = "z";

foreach ($feld_zwei as $wert1) {
   foreach ($wert1 as $wert2) {
     echo $wert2;
   }
}
/**
* für assoziative Arrays, die Ausgabe
* bezieht sich hier auf die Indizes z.B. "a"
**/
$feld_drei = array("a"=>"1","b"=>"2", "c"=>"3","d"=>"4");
foreach ($feld_drei as $key =>$wert_3) {
   echo $key; /* abcd */
}
?>

Erklärung:

Mithilfe des Schlüsselwortes „foreach“ können wir durch ein Array gehen. Wir können einen bestimmten Wert auslesen oder aber auch verändern. Im ersten Beispiel haben wir ein eindimensionales Array namens „$feld_eins“ mit den Werten (1,2,3,4). Dann haben wir den Befehl „foreach“ verwendet, um jeden Wert im Array zu verdoppeln. Damit der Wert des Elements verändert werden kann, müssen wir ein &-Zeichen vor $wert setzen. Nachdem wir den Befehl ausgeführt haben, hat das Array den Inhalt (2,4,6,8). 

Im zweiten Beispiel haben wir ein zweidimensionales Array namens „$feld_zwei“. Hier haben wir eine für PHP ungewöhnliche Zuweisung verwendet, indem wir die Werte des Arrays sichekt zugewiesen haben. Der Inhalt dieses Arrays ist: ("a", "b", "y", "z"). Wir haben wieder den Befehl „foreach“ verwendet, um jeden Wert im Array auszulesen und auf dem Bildschirm auszugeben. 

Im dritten Beispiel haben wir ein assoziatives Array namens „$feld_drei“. Da es sich hierbei um ein assoziatives Array handelt, steht der Schlüssel neben dem Wert. Der Inhalt des Arrays ist: ("a"=>"1", "b"=>"2", "c"=>"3", "d"=>"4"). Auch hier wurde wieder der Befehl „foreach“ verwendet, um jeden Wert im Array auszulesen und auf dem Bildschirm auszugeben.

foreach ist schneller und einfacher als eine vergleichbare while-Schleife. Das folgende Beispiel zeigt die empfohlene Vorgehensweise mit foreach:

Hinweis: Die früher verwendete Kombination aus while(), list() und each() ist seit PHP 8.0 nicht mehr verfügbar, da each() entfernt wurde. Verwenden Sie stattdessen immer foreach:

<?php
/**
* der interne Zeiger wird automatisch durch den Aufruf auf
* das erste Element gesetzt
**/
foreach($feld as $key => $wert){
  $feld[$key] = $wert + 1;
}
?>

Man sollte vor dem Ausführen einer foreach Schleife, die Variable mit dem PHP Befehl is_array() prüfen, da ansonsten eine Fehlermeldung ausgegeben wird, wenn die Variable kein Array ist.

 

Fehlerbehandlung bei foreach

Seit PHP 8.0 wirft foreach einen TypeError, wenn die übergebene Variable kein Array und kein Traversable-Objekt ist. Dieser Fehler kann mit einem try-catch-Block gefangen werden:

<?php
try {
    foreach ($daten as $element) {
        /* Code hier ausführen */
    }
} catch (\TypeError $e) {
    echo 'Fehler: ' . $e->getMessage();
}
?>

Empfohlene Vorgehensweise: Prüfen Sie die Variable vor dem foreach-Aufruf mit is_iterable() oder is_array(), anstatt Fehler erst zur Laufzeit abzufangen:

<?php
if (is_iterable($daten)) {
    foreach ($daten as $element) {
        /* Code hier ausführen */
    }
}
?>

Key-Value-Iteration: Schlüssel und Wert gleichzeitig auslesen

Bislang haben Sie foreach nur über die Werte eines Arrays laufen lassen. In der Praxis brauchen Sie aber sehr oft auch den dazugehoerigen Schlüssel, zum Beispiel bei assoziativen Arrays mit sprechenden Indizes. Genau dafuer gibt es die Variante foreach ($arr as $key => $value). PHP packt sich bei jedem Durchgang das Schlüssel-Wert-Paar in zwei separate Variablen.

<?php
declare(strict_types=1);

$preise = [
    'Apfel'    => 0.45,
    'Banane'   => 0.30,
    'Kirsche'  => 1.20,
];

foreach ($preise as $produkt => $preis) {
    echo $produkt . ': ' . number_format($preis, 2, ',', '.') . " €
";
}
/* Apfel: 0,45 €
   Banane: 0,30 €
   Kirsche: 1,20 € */

Der Variablenname links vom Pfeil ist frei waehlbar. Sie können ihn nennen, wie Sie wollen, denn PHP weist nur den jeweils aktuellen Schlüssel zu. Genauso funktioniert das auch mit numerisch indizierten Arrays. Dort enthält $key dann den fortlaufenden Index ab Null.

Mehrdimensionale Arrays mit verschachteltem foreach

Daten kommen selten flach daher. Wer Datensaetze aus einer Datenbank holt, einen JSON-Stream parst oder eine Konfigurationsdatei einlesen, bekommt fast immer mehrdimensionale Strukturen. Eine verschachtelte foreach-Schleife ist das passende Werkzeug, um durch beliebig tiefe Daten zu wandern. Wichtig ist, dass Sie für jede Ebene eine eigene Laufvariable nutzen, damit Sie sie nicht versehentlich überschreiben.

<?php
declare(strict_types=1);

$bestellungen = [
    'Nico'  => ['Buch', 'Kaffee'],
    'Lena'  => ['Maus', 'Tastatur', 'Monitor'],
    'Tarek' => [],
];

foreach ($bestellungen as $kunde => $artikel) {
    echo $kunde . " bestellt:
";
    foreach ($artikel as $position) {
        echo '  - ' . $position . "
";
    }
}

Wenn Sie die Tiefe Ihrer Struktur vorher nicht kennst, ist eine rekursive Funktion oft sauberer als immer mehr verschachtelte Schleifen. Trotzdem reicht foreach in den meisten Praxisfaellen vollkommen aus, weil Datensaetze meistens nur zwei Ebenen haben.

Iteration mit Referenz: foreach ($arr as &$item)

In der Standardform arbeitet foreach mit Kopien der Werte. Aenderst Sie $item im Schleifenkoerper, wird das Original-Array nicht angefasst. Manchmal wollen Sie genau das aber: die Werte sichekt im Array verändern. Dafuer gibt es das kaufmaennische Und vor der Laufvariable.

<?php
declare(strict_types=1);

$zahlen = [1, 2, 3, 4, 5];

foreach ($zahlen as &$zahl) {
    $zahl = $zahl * 2;
}
unset($zahl); /* WICHTIG: Referenz aufloesen */

print_r($zahlen);
/* Array ( [0] => 2 [1] => 4 [2] => 6 [3] => 8 [4] => 10 ) */

Der Reference-Bug-Klassiker

Vergisst Sie das unset($zahl) nach der Schleife, lebt die Referenz weiter. Greifst Sie später in einer zweiten foreach-Schleife auf $zahl zu, ohne sie neu zu deklarieren, überschreiben Sie das letzte Element Ihres Arrays. Dieser Bug ist berüchtigt und sehr schwer zu finden, weil der Fehler oft weit weg vom Ausloeser auftritt. Mach sich das unset() sichekt nach jeder Referenz-Schleife zur Gewohnheit. Mit unset() brichst Sie die Bindung sauber auf.

foreach mit Generator-Funktionen

Eine Funktion mit yield wird zum Generator. Generatoren liefern Werte einzeln, statt das ganze Ergebnis im Speicher aufzubauen. Genau das macht sie ideal für riesige Listen, Dateizeilen oder unendliche Sequenzen. foreach kann über Generatoren laufen, als waeren sie ganz normale Arrays.

<?php
declare(strict_types=1);

function bisZahl(int $max): \Generator
{
    for ($i = 1; $i <= $max; $i++) {
        yield $i;
    }
}

foreach (bisZahl(5) as $n) {
    echo $n . ' ';
}
/* 1 2 3 4 5 */

Auch yield $key => $value ist erlaubt. Damit können Sie wie bei einem assoziativen Array iterieren, ohne jemals den vollen Datenbestand im RAM zu halten. Das ist besonders praktisch, wenn Sie große Logdateien oder CSV-Exporte verarbeiten.

Destrukturierung: foreach mit list()-Syntax

Seit PHP 7.1 können Sie in foreach sichekt entpacken, was Sie brauchen. Das spart eine Menge Boilerplate-Code, wenn Ihre Datenstruktur aus assoziativen Sub-Arrays besteht. Mehr Hintergrund finden Sie im Tutorial zu list().

<?php
declare(strict_types=1);

$users = [
    ['name' => 'Anna',  'age' => 28],
    ['name' => 'Bjoern', 'age' => 35],
    ['name' => 'Carla', 'age' => 41],
];

foreach ($users as ['name' => $n, 'age' => $a]) {
    echo $n . ' ist ' . $a . " Jahre alt.
";
}

Sie können auf diese Weise gezielt nur die Felder herausziehen, die Sie in der Schleife wirklich brauchen. Das macht den Schleifenkoerper kürzer und besser lesbar. Schreiben Sie trotzdem nur das raus, was im aktuellen Block sinnvoll ist, sonst leidet die Wartbarkeit.

foreach über Iteratoren und IteratorAggregate

Sie können foreach auch auf eigenen Klassen einsetzen. Implementiert eine Klasse das Iterator- oder IteratorAggregate-Interface, behandelt PHP sie wie eine durchlaufbare Sammlung. Das ist die Grundlage für Collections in Composer-Bibliotheken wie Doctrine oder Symfony.

<?php
declare(strict_types=1);

class Tagebuch implements IteratorAggregate
{
    /** @var array<string> */
    private array $eintraege = [];

    public function add(string $text): void
    {
        $this->eintraege[] = $text;
    }

    public function getIterator(): ArrayIterator
    {
        return new ArrayIterator($this->eintraege);
    }
}

$buch = new Tagebuch();
$buch->add('Heute foreach gelernt.');
$buch->add('Morgen Generators.');

foreach ($buch as $eintrag) {
    echo '* ' . $eintrag . "
";
}

Mit IteratorAggregate sparen Sie sich die fünf Pflicht-Methoden des einfachen Iterator-Interface. Sie delegierst die Iteration einfach an einen ArrayIterator oder einen Generator. Klassen werden so auf einen Schlag mit allen foreach-Features kompatibel.

Schleifensteuerung: break und continue

Manche Iterationen sollen nicht immer das ganze Array durchlaufen. Mit break verlassen Sie die Schleife sofort, mit continue ueberspringst Sie nur den aktuellen Durchgang und springst zum nächsten Element. Beide Schluesselworte funktionieren in foreach genauso wie in der for-Schleife oder der while-Schleife.

<?php
declare(strict_types=1);

$kandidaten = ['anna@example.com', '', 'bjoern@example.com', 'noemail'];

foreach ($kandidaten as $eintrag) {
    if ($eintrag === '') {
        continue; /* leere Eintraege ignorieren */
    }
    if (!filter_var($eintrag, FILTER_VALIDATE_EMAIL)) {
        echo 'Ungueltig, Abbruch bei: ' . $eintrag . "
";
        break;
    }
    echo 'OK: ' . $eintrag . "
";
}

Sie können sogar break 2 oder continue 2 schreiben, um aus einer verschachtelten Schleife eine Ebene tiefer auszubrechen. Setzen Sie das aber sparsam ein, sonst leidet die Lesbarkeit.

Funktionale Alternativen: array_map und array_filter

Nicht jede Iteration braucht ein foreach. Wenn Sie nur transformierst oder filterst, sind array_map() und array_filter() oft kürzer und ausdrucksstaerker. Das ist funktionaler Stil und passt gut zu modernen Arrow Functions.

<?php
declare(strict_types=1);

$zahlen = [1, 2, 3, 4, 5, 6];

$verdoppelt = array_map(fn(int $n): int => $n * 2, $zahlen);
$gerade     = array_filter($zahlen, fn(int $n): bool => $n % 2 === 0);

print_r($verdoppelt);
print_r($gerade);

Beide Funktionen erzeugen ein neues Array und verändern das Original nicht. Das macht den Code besser testbar und vermeidet Seiteneffekte. Wenn Sie allerdings beim Iterieren mehrere Aktionen kombinieren wollen, etwa loggen, validieren und transformieren, bleibt foreach die uebersichtlichere Wahl.

Lifecycle einer foreach-Schleife

Das folgende Diagramm zeigt, wie PHP intern bei jedem Durchgang vorgeht. Es greift auf den internen Zeiger der Datenstruktur zu, holt ein Element, führt den Body aus und springt weiter, bis es kein nächstes Element mehr gibt.

flowchart TD
    A[Datenstruktur] --> B[Pointer auf erstes Element]
    B --> C{Element vorhanden?}
    C -- Nein --> F[Schleife beenden]
    C -- Ja --> D[Element zuweisen]
    D --> E[Body ausfuehren]
    E --> G[Pointer auf naechstes Element]
    G --> C

Bei einem leeren Array entscheidet PHP sichekt am ersten Check mit "Nein" und springt ans Ende. Es gibt keinen Fehler, keine Warnung, kein einziger Body-Aufruf. Das ist praktisch, weil Sie sich den expliziten Leer-Check sparen können, sofern Ihr Body-Code tatsaechlich nichts zu tun hat, wenn nichts da ist.

Praxisbeispiel: HTML-Tabelle aus einer Liste rendern

Eine der häufigsten Aufgaben mit foreach ist das Rendern tabellarischer Daten. Hier ein typisches Snippet, das Sie in jedem CMS oder Backend wiederfinden. Es nutzen htmlspecialchars() gegen XSS, damit auch Sonderzeichen sauber in das HTML eingebettet werden.

<?php
declare(strict_types=1);

$produkte = [
    ['name' => 'Tasse', 'preis' => 9.90,  'stock' => 12],
    ['name' => 'Buch',  'preis' => 24.00, 'stock' => 0],
    ['name' => 'Stift', 'preis' => 1.50,  'stock' => 250],
];

echo "<table>
";
echo "  <tr><th>Name</th><th>Preis</th><th>Lager</th></tr>
";
foreach ($produkte as $p) {
    echo '  <tr><td>' . htmlspecialchars($p['name'])
       . '</td><td>' . number_format($p['preis'], 2, ',', '.')
       . ' €</td><td>' . $p['stock']
       . "</td></tr>
";
}
echo "</table>
";

Praxisbeispiel: Summe und Filter in einem Durchlauf

Manchmal wollen Sie in einem einzigen Schleifendurchgang gleich mehrere Ergebnisse berechnen. Das geht mit foreach sehr sichekt und Sie sparen sich mehrere Aufrufe von array_filter() oder array_sum().

<?php
declare(strict_types=1);

$rechnungen = [
    ['betrag' => 49.90, 'bezahlt' => true],
    ['betrag' => 199.00, 'bezahlt' => false],
    ['betrag' => 12.50, 'bezahlt' => true],
    ['betrag' => 80.00, 'bezahlt' => false],
];

$summeOffen   = 0.0;
$anzahlOffen  = 0;

foreach ($rechnungen as $r) {
    if ($r['bezahlt'] === true) {
        continue;
    }
    $summeOffen  += $r['betrag'];
    $anzahlOffen += 1;
}

echo "Offene Rechnungen: $anzahlOffen
";
echo 'Offener Betrag: ' . number_format($summeOffen, 2, ',', '.') . " €
";

Der Trick: Sie kombinierst Filter und Aggregation in einer einzigen Schleife und vermeiden das mehrfache Durchlaufen desselben Arrays. Bei kleinen Datenmengen ist das egal, bei zehntausenden Zeilen merken Sie den Unterschied sofort.

Was passiert bei einem leeren Array?

Eine haeufige Anfaengerfrage lautet: Muss ich vor jedem foreach mit empty() oder count() prüfen, ob überhaupt Daten da sind? Die kurze Antwort: Nein. foreach über ein leeres Array ist voellig harmlos, der Body wird einfach nicht ausgeführt. Es gibt keine Notice, keine Warnung, kein Crash.

<?php
$leer = [];

foreach ($leer as $x) {
    echo "Das wird niemals ausgegeben.
";
}
echo "Code laeuft normal weiter.
";

Eine Prüfung mit empty() macht trotzdem manchmal Sinn, nämlich wenn Sie eine Alternativausgabe brauchen, etwa "Keine Eintraege vorhanden". Dann reicht aber ein einfaches if-else drumherum. Aufpassen müssen Sie nur, wenn Sie etwas anderes als ein Array oder ein iterierbares Objekt übergeben, etwa null. Dann wirft PHP seit Version 8 einen Fehler. Mit dem Null-Coalescing-Operator können Sie in solchen Faellen einen leeren Default setzen: foreach (($daten ?? []) as $eintrag).




weiter zum nächsten Kapitel: Verstehe die Grundlagen von while-Schleife und do-while-Schleife in PHP