PHP/Schleifen

Aus Mikiwiki
< PHP
Wechseln zu: Navigation, Suche

Schleifen werden benötigt, um Programmteile mehrfach durchlaufen zu lassen. Neben der Einsparung an Tipparbeit ist dabei vor allem die variable Festlegung der Schleifendurchläufe interessant. Schleifen ohne feste Laufvariable werden durch eine Bedingung gesteuert. Der Zustand des logischen Ausdrucks bestimmt, ob die Schleife weiter durchlaufen wird oder nicht.

Schleifen mit "while" und "do ... while"

Bei der "while"-Schleife wird die Bedingung mit jedem Eintritt in die Schleife getestet. Solange der Ausdruck "TRUE" zurückgibt, wird die Schleife durchlaufen. Ergibt der Ausdruck also schon beim Eintritt in die Schleife "FALSE", so wird die Schleife gar nicht durchlaufen. Es sollte deshalb vermieden werden, Variablen in Schleifen zu initialisieren und global gültige Zuweisungen vorzunehmen; das wäre schlechter Programmierstil. Zum einen ist es sinnlos, Zuweisungen mehrfach vorzunehmen, wenn sich der Wert nicht ändert. Zum anderen versagen solche Konstrukte, wenn die Bedingung anfangs nicht erfüllt ist. Es sollte auch unbedingt darauf geachtet werden, dass einfache Schleifen eine klare Abbrucjbedingung haben; Endlosschleifen können das System zum Stillstand bringen.

Im folgenden Beispiel links unten bricht die Schleife ab, wenn "$counter" grösser als 6 ist - also nach sieben Durchläufen. Im Beispiel rechts unten geschieht dasselbe, jedoch mit der bereits vom "if"-Befehl her bekannten alternativen Syntax (die in der Praxis allerdings vermieden werden sollte).

<?php
$counter = 0;
$test = 4;
while ($test > $counter) 
{
  echo "Aktueller Zähler: $counter<br />";
  $counter++;
}
?>

Aktueller Zähler: 0
Aktueller Zähler: 1
Aktueller Zähler: 2
Aktueller Zähler: 3

<?php
$counter = 0;
$test = 4;
while ($test > $counter): ?>

Aktueller Zähler: <?php echo $counter; ?> <br />
<?php $counter++;
      endwhile    ?>

Aktueller Zähler: 0
Aktueller Zähler: 1
Aktueller Zähler: 2
Aktueller Zähler: 3

Neben der Anfangsbedingung ist derselbe Ausdruck auch für die Abbruchbedingung zuständig. Die Problematik der Abbruchbedingung kann umgangen werden, indem zusätzlich ein "Notausstieg" eingebaut wird. Das folgende Beispiel zeigt eine fehlerhaft programmierte Schleife - die Abbruchbedingung wird regulär nie erfüllt. Der Notausstieg verwendet den Befehl "break", der die Ausführung an die nächsthöhere Programmebene zurückgibt; das ist normalerweise der Befehl, der auf die schliessende Klammer folgt.

<?php
$counter = 10;
$test = 6;
while ($counter > $test) 
{
  echo "Aktueller Zähler: $counter<br>";
  $counter++;
  if ($counter == 14) break;
}
?>

Aktueller Zähler: 10
Aktueller Zähler: 11
Aktueller Zähler: 12
Aktueller Zähler: 13

Der Test der Bedingung am Anfang hat einen wesentlichen Nachteil, wenn der Blockinhalt für die weitere Programmfortsetzung unbedingt erforderlich ist. Es ist möglich, dass die Bedingung so wirkt, dass der Inhalt nie durchlaufen wird. Um das sicherzustellen, gibt es folgende Konstruktion:

do { block } while (Bedingung)

Der einzige Unterschied ist die Reihenfolge der Abarbeitung. Zuerst wird die Schleife einmal durchlaufen und am Ende die Abbruchbedingung getestet. Auch dann, wenn die Abbruchbedingung beim Schleifeneintritt "FALSE" ist, wird der Block mindestens einmal ausgeführt. Natürlich ist genauso und aus demselben Grund der Einsatz von "break" möglich. Für diese Form gibt es keine alternative Syntax.

<?php
$counter = 0;
$test = 3;
do 
{
  echo "Aktueller Zähler: $counter<br />\n";
  $counter++;
} while ($counter <= $test)
?>

Aktueller Zähler: 0
Aktueller Zähler: 1
Aktueller Zähler: 2
Aktueller Zähler: 3

Der Befehl "continue" erzwingt das Auslösen des Bedingungstests und setzt die Ausführung sofort mit dem Test der Schleifenbedingung fort. Ist die Schleifenbedingung in diesem Augenblick "FALSE", so wird die Schleife mit dem Befehl "continue" verlassen. Das folgende Beispiel zeigt eine Anwendung, in der mit einer weiteren "if"-Bedingung ein Teil des Schleifenblocks ausgeblendet wird. Die Schleife zeigt hier nur gerade Zahlen an.

<?php
$counter = 0;
$test = 6;
while ($counter < $test) 
{
  if ($counter % 2) 
  {
    $counter++;
    continue;
  } 
  echo "Aktueller Zähler: $counter<br />\n";
  $counter++;
}
?>

Aktueller Zähler: 0
Aktueller Zähler: 2
Aktueller Zähler: 4

Zählschleifen mit "for"

Die feste Vorgabe von unteren und oberen Grenzwerten ist keine typische Anwendung von "while"-Schleifen. Dafür wird besser die komplexere "for"-Schleife eingesetzt. Die Abbruchbedingung ist auch hier ein normaler logischer Ausdruck. Zusätzlich wird eine numerische Variable mitgeführt - die Zählvariable. Als Variablennamen kommen typischerweise einzelne Buchstaben (z. B. "$i" oder "$k") zum Einsatz; dies ist keine Vorschrift, sondern erleichtert die Lesbarkeit von Skripten.

for(<Startwert>, <Bedingung>, <Iteration>);

Die Schleife im folgenden Beispiel unten links zählt von 0 bis 3. Unten rechts wird die (nicht empfohlene) alternative Syntax mit "endfor" gezeigt.

<?php
for($i=0; $i <= 3; $i++) 
{
  echo "i ist jetzt: $i<br />";
}
?>

i ist jetzt: 0
i ist jetzt: 1
i ist jetzt: 2
i ist jetzt: 3

<?php for($i=0; $i <= 3; $i++): ?>
i ist jetzt: <?php echo $i ?> <br />
<?php endfor; ?>

i ist jetzt: 0
i ist jetzt: 1
i ist jetzt: 2
i ist jetzt: 3

Die Variable in den drei Elementen der "for"-Schleife muss nicht durchgehend verwendet werden. Das ist zwar im Hinblick auf lesbare Skripte zu empfehlen, aber nicht zwingend, wie das folgende Beispiel zeigt.

<?php
$j = 0;
for($i=0; $i <= 5; $j++) 
{
  echo "$i. j ist jetzt: $j<br />\n";
  $i += 2;
}
?>

0. j ist jetzt: 0
2. j ist jetzt: 1
4. j ist jetzt: 2

Alle drei Parameter der "for"-Schleife sind optional. Ohne Iterationsvariable wird die Schleife endlos durchlaufen. In diesem Fall kann die Schliefe über "break" mit einer zusätzlichen Bedingung verlassen werden. Ebenso kann mit "continue" der Test der Abbruchbedingung und die Ausführung des Iterationsschrittes erzwungen werden.

<?php
for(;;) 
{
  $i++;
  if ($i % 2) 
  {
    continue;
    $i++;
  }
  echo "i ist jetzt: $i<br />\n";
  if ($i > 5) break;
}
?>

i ist jetzt: 2
i ist jetzt: 4
i ist jetzt: 6

Der flexible Umgang mit den Schleifenvariablen kennt so gut wie keine Grenzen. Auch das folgende Beispiel ist syntaktisch richtig. Eingesetzt werden gleich zwei Variablen. Es spielt also offensichtlich keine Rolle, ob Variablen zum Einsatz kommen oder nicht.

<?php
for($i = 0, $j = 5; $i < $j; $i++) 
{
  $j--;
  echo "j ist jetzt: $j<br />\n";
  echo "i ist jetzt: $i<br />\n";
}
?>

j ist jetzt: 4
i ist jetzt: 0
j ist jetzt: 3
i ist jetzt: 1
j ist jetzt: 2
i ist jetzt: 2

Zur einfachen Ausgabe einer Liste kann der entsprechende Befehl auch sehr kurz ausfallen. Innerhalb des "for"-Befehls können durch Kommata getrennt weitere Befehle eingebaut werden. Im Beispiel wird nicht zufällig der Befehl "print" anstatt des flexibleren "echo" verwendet; "echo" gibt nichts zurück, während "print" die Ausführung im Erfolgsfall mit "TRUE" quittiert. Normalerweise wird dieser Rückgabewert fortgeworfen. Die "for"-Schleife erwartet jedoch von jedem direkt eingegebenen Wert, dass er sich als Ausdruck verhält und also etwas zurückgibt.

<?php
for($i = 0, $j = 5; $i < $j; $i++, $j--, print("$i<br />\n"));
?>

1
2
3

Bearbeitung von Arrays mit "foreach"

Mit "foreach" steht eine alternative Form der "for"-Schleife zum Durchlaufen von Arrays zur Verfügung. Gegenüber der "while"-Schleife mit "list" und "each" vereinfacht sich die Syntax deutlich. Dabei wird das Array "$array" von Anfang bis Ende durchlaufen und bei jedem Schleifendurchlauf wird das aktuelle Element der Variablen "$element" zugewiesen. Jedes Arrayelement kann wiederum ein Array sein, mit einer verschachtelten "foreach"-Schleife könnte dann auch dieses Array ausgewertet werden.

foreach($array as $element)
{
  ...
}

Zuerst ein einfaches Beispiel mit einem assoziativen Array.

<?php
$myarray = array("x1", "x2", "x3");
foreach($myarray as $xwert) 
{
  echo "$xwert <br />\n";
}
?>

x1
x2
x3

Typischerweise ist es erlaubt, einzelne Elemente eines solchen Arrays mit unterschiedlichen Datentypen zu belegen; das können auch weitere Arrays sein. Das folgende Beispiel zeigt, wie solche komplexen Gebilde angezeigt werden können. Der Ausgabe mangelt es zwar an der Formatierung, die Informationen über die Struktur des Arrays sind aber klar erkennbar.

<?php
$myarray = array("x1", 45, array(2, 4, 6, 8), "x4");
foreach($myarray as $val) 
{
  if (gettype($val) == "array") 
  {
    echo "<p>Inneres Array:<br />\n";
    foreach($val as $innerval) 
    {
      echo "-- $innerval<br />\n";
    }
    echo "Ende inneres Array.</p>\n";
  } 
  else 
  {
    echo "$val<br />\n";
  }
}
?>

x1
45

Inneres Array:
-- 2
-- 4
-- 6
-- 8
Ende inneres Array.

x4

Verarbeitung assoziativer Arrays

Werden Arrays mit Schlüssel-/Wertepaaren gebaut, so kann "foreach" mit einer erweiterten Syntax diese Paare direkt auslesen. Die grundlegende Syntax lautet wie folgt. Dabei wird der Operator "=>" eingesetzt, der schon bei der Konstruktion des Arrays verwendet wurde.

foreach(<array> as <schluessel> => <wert>)
{
  ...
}

Das folgende Beispiel zeigt die Anwendung.

<?php
$myarray = array("Name"    => "Krause",
                 "Ort"     => "Berlin",
                 "PLZ"     => 12683,
                 "Vorwahl" => "030");
foreach($myarray as $key => $value) 
{
  echo "Feld $key hat den Wert $value<br />\n";
}
?>

Feld Name hat den Wert Krause
Feld Ort hat den Wert Berlin
Feld PLZ hat den Wert 12683
Feld Vorwahl hat den Wert 030