PHP/Bedingungen

Aus Mikiwiki
< PHP
Wechseln zu: Navigation, Suche

Bedingungen sind das wesentliche Element zur Programmsteuerung. Das Programm fällt anhand der Bedingung eine einfache Entscheidung: Ja oder Nein. Entsprechend müssen Ausdrücke, die in den Bedingungsbefehlen eingesetzt werden, logische Ausdrücke sein. Das Ergebnis muss für PHP als wahr ("TRUE") oder falsch ("FALSE") erkennbar sein. Um Ausdrücke zu konstruieren, werden Operatoren benötigt. Dabei werden logische Operatoren und Vergleichsoperatoren unterschieden. Den eigentlichen Programmablauf steuern dann Bedingungen wie "if". Auch die Befehle zur Schleifensteuerung nutzen logische Ausdrücke.

Logische Operatoren

In vielen Abfragen wird eine logische Entscheidung (Ja / Nein) verlangt. Mit besonderen Operatoren können Ausdrücke verknüpft werden. Das Ergebnis eines richtigen logischen Ausdrucks ist immer "0" ("FALSE", falsch) oder "1" ("TRUE", wahr). Folgende Ausdrücke zeigen die Anwendung.

Ausdruck Bedeutung
$x and $y
$x && $y
Ist wahr, wenn $x und $y wahr ist.
$x or $y
$x || $y
Ist wahr, wenn $x oder $y wahr ist.
$x xor $y Ist falsch, wenn $x und $y gleich sind (exklusives Oder).
!$x Negiert den Wert "FALSE=True", "True=FALSE".

Zwischen der Form "and" und "&&" bzw. "or" und "||" gibt es keinen Unterschied in der Ausführung der Operation. Bei der Notation sieht es anders aus. Die Darstellung mit Schlüsselworten statt Operatorsymbolen spart Klammern. Der folgende Ausdruck muss mit dem Schlüsselwort "and" geschrieben werden.

if ($a == 45 and $b == 23)

Bei Verwendung der Symbole "&&" sind zusätzliche Klammern nötig.

if (($a == 45) && ($b == 23))

Vergleichsoperatoren

Zum erstellen komplexer logischer Ausdrücke werden folgende Vergleichsoperatoren benötigt.

Operatorsymbol Bedeutung
== Gleichheit (nicht zu verwechseln mit dem Zuweisungsoperator "=" !)
!= Ungleichheit
=== Identität. Damit wird nicht nur der Inhalt einer Variable sondern auch der Datentyp getestet.
!== Nicht identisch. Damit wird nicht nur der Inhalt einer Variable sondern auch der Datentyp getestet.
> Grösser als
< Kleiner als
>= Grösser als oder gleich
<= Kleiner als oder gleich

Mit den Identitätsoperatoren "===" und "!==" wird nicht nur der Inhalt einer Variable sondern auch der Datentyp getestet. Durch die interne Typumwandlung führen sonst Vergleiche zwischen Zeichenketten, die Zahlen enthalten, und den unmittelbar angegebenen Zahlen zu einer Übereinstimmung. Mit dem Identitätsoperator ist das nicht der Fall.

Auswertung von Bedingungen mit "if"

Die Syntax des Befehls "if" lehnt sich an die Programmiersprache C an. Der "if"-Befehl besteht aus dem Schlüsselwort und dem in runden Klammern stehenden logischen Ausdruck. Wenn der Ausdruck wahr wird, so wird der nachfolgende Befehl oder Block (in geschweiften Klammern) ausgeführt. Ist der Ausdruck falsch, so wird die Programmausführung mit dem nächsten Befehl oder dem nachfolgenden Block fortgesetzt.

if ($tag == "Montag") echo "Heute ist Montag";

Folgen mehrere abhängige Befehle, so ist der Code folgendermassen zu schreiben.

if ($tag == "Montag")
{
  echo "Heute ist Montag";
  echo "<br />;
}

Das folgende Beispiel nutzt die Datumsfunktionen, um eine entsprechende Begrüssung zu erzeugen. Der schwerwiegendste Nachteil ist hier, dass nach einer erfolgreichen Prüfung weitere Tests erfolgen, obwohl diese theoretisch nicht mehr erfüllt sein können. Funktionierender Code ist also nicht unbedingt guter Code. Diese Aufgabe ist mit dem Befehl "switch" besser zu lösen.

<?php
$tag = date("l"); 
if ($tag == "Monday")    { echo "Heute ist Montag"; }
if ($tag == "Tuesday")   { echo "Heute ist Dienstag"; }
if ($tag == "Wednesday") { echo "Heute ist Mittwoch"; }
if ($tag == "Thursday")  { echo "Heute ist Donnerstag"; }
if ($tag == "Friday")    { echo "Heute ist Freitag"; }
if ($tag == "Saturday")  { echo "Heute ist Samstag"; }
if ($tag == "Sunday")    { echo "Heute ist Sonntag"; }
?>
Heute ist Dienstag

Grundsätzlich kann der "if"-Befehl unbegrenzt verschachtelt werden, in jedem Block kann sich also wieder ein "if"-Befehl befinden. Das sollte allerdings vermieden werden, da es fast immer bessere Lösungsmöglichkeiten gibt.

Oft ist es notwendig, nicht nur auf das Eintreten eines Ereignisses zu reagieren, sondern auch die negative Entscheidung zu behandeln. In solchen Fällen wird der "if"-Befehl um "else" ergänzt. Der Befehl oder Block nach "else" wird dabei ausgeführt, wenn die Bedingung nicht zutrifft. Das folgende Beispiel führt eine zweistufige Entschdiung durch; gleichgültig wie das Datum lautet muss in jedem Fall eine Ausgabe erfolgen.

<?php
$tag = date("w");
if ($tag == 0 or $tag == 7) { echo "Wochenende!"; }
else                        { echo "Arbeitszeit"; }
?>
Arbeitszeit

Das vorhergehende Beispiel könnte auch mit "elseif" geschrieben werden; dabei wird im "else"-Zweig noch ein weiterer "if"-Befehl eingebaut. "elseif" spart also im wesentlichen nur Schreibarbeit. Eine mögliche Anwendung könnte wie im folgenden unten links aussehen. Die unten rechts gezeigte alternative Syntax von PHP ermöglicht durch die Einführung des Schlüsselworts "endif", das Blockende ausdrücklich zu bestimmen; die Klammern können dafür entfallen. Die "else"- und "elseif"-Befehle sind mit einem Doppelpunkt zu versehen, um die Zugehörigkeit zu einem Block zu kennzeichnen; auch hier können die geschweiften Klammern entfallen.

<?php
$tag = date("w");
if ($tag == 0 or $tag == 7) { echo "Wochenende!"; }
elseif ($tag == 5)          { echo "Fast Wochenende..."; }
else                        { echo "Arbeitszeit"; }
?>
Arbeitszeit
<?php
$tag = date("w");
if ($tag == 0 or $tag == 7)
{ echo "Wochenende!"; }
elseif ($tag == 5)
{ echo "Fast Wochenende..."; }
else
{ echo "Arbeitszeit"; }
?>
<?php $tag = date("w");
      if ($tag == 0 or $tag == 7): ?>
Wochenende!
<?php elseif ($tag == 5): ?>
Fast Wochenende...
<?php else: ?>
Arbeitszeit
<?php endif ?>

Die hier eingesetzte Funktion "date" kann mit einem zweiten Parameter erweitert werden, der den Zeitwert bestimmt, für den das Datumsformat gilt. Zeitwerte in PHP entsprechen dem Unix-Zeitstempel, also der Anzahl der Sekunden seit dem 1. Januar 1970. Das schränkt den Wertebereich natürlich etwas ein. Um die Beispiele für jeden Tag zu simulieren, kann die Funktion "mktime" als zweiter Parameter in der Funktion "date" verwendet werden; mit "mktime(0,0,0,7,13,99)" wird beispielsweise der 13. Juli 1999 simuliert.

Der trinäre Bedingungsoperator

PHP kennt (wie C) eine Kurzschreibweise für den sogenannten trinären Bedingungsoperator.

$variable = "test" ? $result = TRUE : $result = FALSE;

Tatsächlich ist die gesamte Konstruktion ein Ausdruck; Ausdrücke geben immer ein Ergebnis zurück. Eleganter ist deshalb folgende Schreibweise.

$result = $variable == test ? TRUE : FALSE;

Damit lassen sich Ausdrücke oft kürzer und lesbarer gestalten. Werden dagegen komplizierte Bedingungen entworfen, so leidet die Lesbarkeit und die klassische Form mit "if" ist angebrachter. Die drei Elemente haben folgende Bedeutung.

<Logischer Ausdruck> ? wenn TRUE : wenn FALSE

Diese Schreibweise ist eigentlich ein Operator - der sogenannte trinäre Operator. Wichtig ist daran zu denken, dass der Operator Ausdrücke erwartet, die etwas zurückgeben. Folgender Ausdruck funktioniert also nicht, da der Befehl "echo" keine Funktion ist und nichts zurückgibt.

$a == 66 ? echo "A ist 66" : echo "A ist nicht 66";

In diesem Fall müsste die Funktion "print" verwendet werden, die das was zum Webbrowser ausgegeben wird auch zurückgibt. Effektiver ist aber das folgende Beispiel.

<?php
$test = 3;
echo $test == 3 ? "Drei" : "Nicht drei";
?>
Drei

Mehrfachauswertungen mit "switch"

Beim Test mehrerer aufeinanderfolgender Bedingungen gegen ein und dieselbe Variable ist der "if"-Befehl sehr aufwendig. Der Befehl "switch" baut solche Listen eleganter auf und ist allgemein etwas schneller als Kombinationen aus "if" und "else". Zudem sind solche Verzweigungsbäume auch leichter lesbar und durch die Schreibweise weniger anfällig gegen Tippfehler.

Die zu testende Variable (hier "$stunde") steht im Befehl "switch" selbst. Die auf Gleichheit zu testenden Testwerte stehen in den einzelnen "case"-Abschnitten. Findet "switch" eine zutreffende Bedingung, so wird nach dem "case"-Befehl mit der Ausführung des Codes begonnen; weitere "case"-Befehle werden nicht ausgewertet, die enthaltenen Befehle werden aber ausgeführt. Ist das nicht beabsichtigt, so muss der "switch"-Block mit "break" ausdrücklich verlassen werden. Der "default"-Zweig des "switch"-Befehls wird ausgeführt, wenn keine andere Bedingung zutrifft. "default" wird allerdings auch erreicht, wenn hinter einer zutreffenden Bedingung kein "break" erfolgte.

<?php
$stunde = date("H");
switch($stunde)
{
  case 8:
    echo "Guten Morgen";
    break;
  case 9:
    echo "Bisschen spät dran heute?";
    break;
  case 10:
    echo "Jetzt gibt's Stunk";
    break;      
  default:
    echo "Sonstwann am Tage...";
}
?>
Sonstwann am Tage...

Im folgenden Beispiel wird gezeigt, dass die nach dem "case"-Befehl stehenden Befehle ebenfalls ausgewertet werden, wenn, das nicht mit dem Befehl "break" ausdrücklich verhindert wird. Natürlich ist die Ausgabe einer bestimmten Anzahl von Zeichen mit entsprechenden Funktionen oder Schleifen einfacher und eleganter lösbar. Dennoch kann der gezielte Einsatz (oder Nicht-Einsatz) von "break" raffinierte Konstruktionen schaffen.

<?php
$status = 3;
switch($status)
{
  case 4: echo "|";
  case 3: echo "|";
  case 2: echo "|";
  case 1: echo "|";   
}
?>
|||

Die Beschränkung des Bedingungstests mit dem Befehl "switch" auf Gleichheit kann als Behinderung erscheinen. PHP kennt allerdings eine erweiterte Notation der Syntax, bei der mehrere Vergleiche hintereinander ausgeführt werden, wobei die Operanden gewissermassen oder-verknüpft sind.

<?php
$tag = date("w");
switch ($tag)
{
  case 1: case 2:
    echo "Wochenanfang";
    break;
  case 6: case 7: case 0: case "six":
    echo "Wochenende";
    break;
  default:
    echo "In der Woche";
}
?>
Wochenanfang

Etwas trickreicher ist die Veratuschung der Operatoren, was dem "switch"-Befehl eine unbegrenzte Funktionalität verleiht. Das folgende Skript zeigt den Tagesabschnitt abhängig von der aktuellen Zeit an. Die Bedingungen können beliebig gestaltet werden. Wichtig ist nur, dass eine der Bedingungen "TRUE" werden kann, damit der Vergleich erfüllt wird. Ebenso kann natürlich "FALSE" angegeben werden, wenn die Nichterfüllung einer Bedingung interessant ist.

<?php
$hour = date("H");
switch (TRUE) 
{
  case ($hour > 6 and $hour <= 10):
    echo "Vormittags";
    break;
  case ($hour > 10 and $hour <= 14):
    echo "Mittags";
    break;
  case ($hour > 14 and $hour <= 18):
    echo "Nachmittags";
    break;
  case ($hour > 18 and $hour <= 22):
    echo "Abends";
    break;
  default: 
    echo "Nachts";
}
?>
Mittags