Wenn ein String false ist …

Wie ich neulich dazugelernt habe, unterscheidet PHP in Funktionen und Sprachkonstrukte (werden in guten Editoren auch farblich anders hervorgehoben als Funktionen). Und da überlegte ich, ob man auf Grund der Tatsache, dass Sprachelemente sehr schnell sind, nicht irgendwelche logischen Elemente durch eben diese ersetzen kann. Beim Durchschauen habe ich dabei eine der simpelsten Logik-Operationen entdeckt, die in vielen Anwendungen vorkommt: Die Prüfung, ob ein String leer, null, false oder 0 ist.

Mir sind 3 offensichtliche Lösungen eingefallen: Das Sprachelement empty(), der Vergleich !=““ bzw. !=0 und dann noch der Vorteil der schwachen Datentypen in PHP: einfach if($variable).
Das ganze in Code:

$i = "";
 
// empty-Variante
if(empty($i)) echo "leer";
 
// Vergleich
if($i=="") echo "leer";
 
// Boolean-Variante
if(!$i) echo "leer";

Die Vermutung, die ich vor dem Benchmark hatte, war folgende: Der Vergleich ist eine recht komplizierte Geschichte. Das weiß man spätestens, wenn man im Rahmen irgendeiner Informatik-Ausbildung dazu gezwungen wurde das Vergnügen hatte mal eine Funktion zum Vergleichen zu programmieren.
Zu prüfen, ob der Inhalt einer Variablen leer ist, ist aber in Wirklichkeit viel einfacher. Das Sprachkonstrukt empty() arbeitet effektiver, da es eben nur diesen einen Vergleich auf ==““ (bzw. ==0, ==false und ==null) durchführen kann und dazu noch im Core implementiert ist. Dadurch entfällt viel Overhead.
Zusätzlich wirft empty() kein Warning, wenn die Variable noch gar nicht deklariert wurde.

Die Arbeit nur über die Angabe des Variablennamens funktioniert auf diese Art nur in Scriptsprachen, die typenlos oder schwach typengebunden sind. Beispiele hierfür sind Perl oder eben auch PHP.
Dabei gilt eine Variable als false, wenn Sie entweder leer (=““), 0, false oder null ist. Andernfalls ergibt die Abfrage true.

Bei der Arbeit per if($variable) ist darauf zu achten, dass die Variable vorher unbedingt deklariert werden muss, weil es sonst ein Warning geben kann.
Ich vermute deshalb, dass empty() intern in etwa so umgesetzt ist:

function empty($i) {
return (isset($i) && $i);
}

Möglicherweise sind damit folgende Ergebnisse zu begründen:

Datei Gesamtlaufzeit durchschnittliche Laufzeit pro Durchlauf Verhältnis zur schnellsten Variante
result_boolean.php 35.440962 s 3.544 ms 100 %
result_empty.php 38.74748 s 3.807 ms 107 % (+ 7%)
result_equal.php 42.410984 s 4.241 ms 120 % (+ 20%)

Wir stellen fest, dass der Vergleich ==““ nur suboptimal ist. Ich habe diese Variante bisher tatsächlich benutzt, aber nach diesem Test, werde ich die Scripte wohl nochmal überarbeiten…
Eindeutiger Testsieger ist die Variante direkt und allein über den Variablennamen. An dieser Stelle sieht man auch, dass empty() nur nötig ist, wenn man die Variable tatsächlich nicht deklariert hat. Das wird aber eigentlich nur bei einer Prüfung auf $_GET-Parameter benötigt, wenn immer mal eine unerschiedliche Anzahl an GET-Parametern übertragen wird.

Also schauen Sie sich einfach mal Ihre Scripte an und gucken, wie oft Sie auf ==0 oder ==““ prüfen. In fast jeder PHP-Datei kommt eine solche Abfrage vor. Simultan kann man das ganze Spiel natürlich auch für !=““, !=0, !=null führen. Für all diese Fälle reicht ein if($i) ....
Aber immer aufpassen, ob dadurch die Logik gleich bleibt. Wenn man nämlich prüfen möchte, ob der User wirklich nichts eingegeben hat oder er eine 0 eingegeben hat, funktioniert wirklich nur if($eingabe==""). Die Prüfung auf empty() bzw. if($eingabe) würde in beiden Fällen true ergeben.

Die Quelltexte und die Ergebnisse können wie immer heruntergeladen werden.

Jan hat 152 Beiträge geschrieben

12 Kommentare zu “Wenn ein String false ist …

  1. Martin sagt:

    Netter Beitrag, aber der direkte, typsichere Vergleich fehlt.

    if ($foo === true) bzw. === null/0/false/““ aus?

    Ich gehe mal davon aus, dass die Variante die schnellste ist?! Hier muss zumindest nicht auf in einen anderen Typ gecastet werden.

  2. Leif sagt:

    Wenn dein String === true ist, dann ist dein Algo krude. Ein String kann leer sein, null oder gefüllt. Er ist kein bool’scher Wert oder eine Zahl, sondern eine Zeichenkette.

  3. Leif sagt:

    Missverständnis. Ich benutze die Variante ja auch gern. Nur bezogen auf den Algo ist es krude. Wenn ich eine Variable als String verwende, dann schreibe ich dort niemals den Wert true rein. Wer macht sowas schon?
    Einige PHP-Funktionen können sowas machen, aber dann bin ich mental darauf eingestellt, dass ich eine Rückgabe erwarte, die nicht zwingend ein String ist. Es handelt sich also im Kontext des Algos nicht um einen String.

  4. Daniel sagt:

    Hier schreiben doch mehrere Leute. Leider sieht man nie wer der Autor ist, um mal auf diesen zu verweisen oder anzusprechen.

    Wäre super, wenn ihr noch einbauen würdet, dass der Autor des Beitrags ausgegeben wird.

  5. Sebastian sagt:

    Den unterschied zu kennen ist erstmal das wichstigste:

    empty($x) und if(!$x) geben TRUE zurück wenn:

    $x = !isset($x),Array(),NULL,“0″,0,FALSE,““

    $x == „“ gibt TRUE zurück wenn:

    $x = !isset($x),NULL,0,FALSE,““

    wie gesehen sind beide also nicht gleichwertig. das heißt also ich muss selbst besser auf rückgabewerte uä. achten, was schnell zu unerwünschten ergebnissen führen kann. und den fehler hier zu finden kann stunden dauern. deswegen immer auf die strikte prüfung zurückgreifen:

    if($x===““)

    dann weiß ich mit sicherheit, das der string wirklich „“ entspricht und nicht irgenwas anderem.

  6. admin sagt:

    @Daniel: Leider schreiben derzeit nicht mehrere Leute. Diejenigen, die sich gemeldet haben (und sich auch kurz vorgestellt hatten), haben leider nur wenig Zeit, deshalb stammen die meisten Beiträge von mir.
    Es gibt noch ein paar Beiträge von Gastautoren, die mir diese zur Verfügung gestellt haben, aber bei diesen Beiträgen erwähne ich den Autor natürlich auch(meist auch mit Link zu dessen Website oder Blog).

    Wenn also wieder jemand Lust zum Schreiben hat, darf er sich gern bei mir melden! Ich möchte nur nicht alle 2 Wochen ein neues Thema erstellen, wo ich nach Mitschreibern suche. Das wirkt so wie betteln 😉

  7. Biggy sagt:

    Also für mich liest sich das wie Fachchinesisch, mir wurde allerdings mitgeteilt, dass deine Aufführungen hier hochinteressant sind! Das wollte ich dir nur mal als Kommentar hierlassen 😉

    Viele Grüße
    Biggy

  8. Christian sagt:

    empty() überprüft dazu auch noch $var=‘ ‚; (also leerzeichen) und gibt das richtig aus. bei if($var==“) würde das falsche rauskommen. empty ist also auf jeden fall zu bevorzugen (und auch das schnellste).

Eine Antwort schreiben

Ihre E-Mail-Adresse wird nicht veröffentlicht. Benötigte Felder sind markiert mit *

You may use these HTML tags and attributes: <a href=""> <blockquote cite=""> <pre lang=""> <b> <strong> <i> <em>