Jörg: php PHP Warning: Undefined array key

Hallo,

ich versuch grad mal, ein paar Warnings zu eliminieren, dabei fällt mir auf, dass ich in der Vergangenheit schlicht Indexe aus den $_POST, $_GET oder $_REQUEST Arrays benutzt habe, ohne zuvor nachzusehen, ob sie überhaupt existent sind.

also:

if ($_POST['bla'] == 'blub') {
// do something
}

Jetzt suche ich nach einer eleganten Lösung, wie ich diese Fehler behandeln kann.

Überall if (isset() && ...) zu notieren, ist halt sehr viel Arbeit.

Habt Ihr einen Tip für mich?

Gruß, Jörg

  1. Hallo Jörg,

    tun musst Du auf jeden Fall was. Am elegantesten könnte der Null-Koaleszenz Operator sein:

    if (($_POST['bla'] ?? '') == 'blub') {
    }
    

    Der Ausdruck (a ?? b) liefert den Wert von a (Variable, Funktionsaufruf, Arrayzugriff), wenn es nicht null ist. Und wenn es null ist, liefert er b (Variable, Konstante, Funktionsaufruf, mit define festgelegter Wert, etc). Gleichzeitig unterdrückt ?? auch die Notices bei undefinerten Array-Keys.

    Kann man auch verketten: $a ?? $b ?? $c ?? $d liefert den ersten dieser vier Werte, der nicht null ist. Von der Rangfolge ist ?? ziemlich niedrig, zwischen || und ?:.

    Rolf

    --
    sumpsi - posui - obstruxi
    1. Hallo Jörg,

      tun musst Du auf jeden Fall was. Am elegantesten könnte der Null-Koaleszenz Operator sein:

      if (($_POST['bla'] ?? '') == 'blub') {
      }
      

      Hallo Rolf,

      oh, gut, dass ich nachgefrat habe.
      Genau sowas habe ich gesucht, danke! 👍

      Jörg

    2. Wie benutze ich den bei einem mehrdimensionalen Array?

      $_POST['bla']['blub]
      

      Eher so?

      ($_POST['bla']['blub'] ?? '')
      

      oder so:

      ($_POST['bla'] ?? '' ['blub'])
      

      Jörg

      1. Hallo

        Wie benutze ich den bei einem mehrdimensionalen Array?

        $_POST['bla']['blub]
        

        Eher so?

        ($_POST['bla']['blub'] ?? '')
        

        wenn du explizit die Existenz von $_POST['bla']['blub'] prüfen willst, ja.

        oder so:

        ($_POST['bla'] ?? '' ['blub'])
        

        Der Ausdruck prüft nur die Existenz von $_POST['bla']. Wenn es $_POST['bla']['schnisselschnassel'] geben sollte, wird $_POST['bla'] wahr sein, auch wenn es $_POST['bla']['blub'] nicht gibt. Zudem möchte ich bezweifeln, dass der Ausdruck mit dem abschließenden ['blubb'] überhaupt syntaktisch korrekt ist.

        Tschö, Auge

        --
        200 ist das neue 35.
        1. Hallo Auge,

          wenn du explizit die Existenz von $_POST['bla']['blub'] prüfen willst, ja.

          Stimmt, will ich.

          Zudem möchte ich bezweifeln, dass der Ausdruck mit dem abschließenden ['blubb'] überhaupt syntaktisch korrekt ist.

          Doch, scheint korrekt zu sein, jedenfalls meckert php nicht "fatal" darüber.

          Jörg

        2. Hallo,

          ($_POST['bla'] ?? '' ['blub'])
          

          Zudem möchte ich bezweifeln, dass der Ausdruck mit dem abschließenden ['blubb'] überhaupt syntaktisch korrekt ist.

          ist er: Das ist die Schreibweise eines Array-Literals, das als einziges Element einen String enthält.

          Also syntaktisch korrekt, aber hier relativ sinnfrei.

          Einen schönen Tag noch
           Martin

          --
          "Formschön, wetterfest, zweckfrei, und gegen Aufpreis auch entnehmbar."
          - Loriot, Familien-Original-Benutzer
          1. Hallo Martin,

            Das ist die Schreibweise eines Array-Literals, das als einziges Element einen String enthält.

            Nein.

            Dieser Ausdruck enthält:

            • $_POST - ein Superglobales Array
            • Einen Array-Access Operator []
            • Ein String-Literal 'bla'
            • Den null-coalescense Operator
            • Einen Leerstring
            • Einen Array-Access Operator []
            • Ein String-Literal 'blub'

            Der Term ['blub'] wäre dann und nur dann ein Array-Konstruktor, wenn links davon ein Operator stände (oder der Ausdruck beginnen würde). Es steht aber ein Wert davor. Deshalb ist es der Array-Access Operator. Ja, das ist scheußlich. Und irgendwie kommt PHP damit klar.

            Nächste Frage ist die nach der Operatorpriorität. Leider ist die Rangfolgetabelle von PHP hier unvollständig, die Zugriffsoperatoren -> und [] fehlen. Es ist aber aus anderen Sprachen bekannt, dass diese Operatoren ziemlich hoch priorisiert sind. Array Access ist definitiv höher priorisiert als ??.

            Solange $_POST['bla'] also einen Wert liefert, wird der Teil rechts vom ?? ignoriert.

            Ist $_POST['bla'] nicht belegt, wird der Teil rechts vom ?? ausgewertet. Und das wäre dann ''['blub']. Also: Ein Leerstring, in dem der String-Key 'blub' gesucht wird. Diese Operation ist für Strings nicht zulässig und ein TypeError fliegt.

            Was ist mit ($_POST['bla'] ?? '')['blub']?

            Wenn $_POST['bla'] einen Wert liefert, wird der Teil rechts vom ?? ignoriert. Durch die Klammerung wird aber DANN im Inhalt von $_POST['bla'] der String-Key 'blub' gesucht. Was das Gewünschte ist.

            Wenn $_POST['bla'] einen Wert liefert, wird der Teil rechts vom ?? ausgewertet. Mit der Folge, dass im Leerstring der String-Key 'blub' gesucht wird. Was einen TypeError auslöst.

            Gucken wir uns $_POST['bla']['blub'] ?? '' an.

            Das sind zwei Array Access Operatoren, die werden von links nach rechts ausgeführt.

            Ist $_POST['bla'] nicht gesetzt, kommt dabei null 'raus (und eine Meldung). Auf diesen null-Wert wird nun der Array Access Operator angewendet, um 'blub' zu ermitteln. Man würde einen TypeError erwarten. Aber das passiert nicht. Es kommt '' heraus.

            Ist $_POST['bla'] auf ein nicht-Array gesetzt, wird ['blub'] auf diesen nicht-Array Wert angewendet. Man würde ebenfalls einen TypeError erwarten. Aber das passiert nicht. Es kommt '' heraus.

            Ist $_POST['bla'] auf ein Array gesetzt, wird ['blub'] auf dieser Array angewendet. Ist dort der Key 'blub' enthalten, wird er ausgelesen. Andernfalls kommt null raus (und eine Meldung) und ?? liefert das '' dazu.

            Dieser Term tut also genau das gewünschte. Aber warum? Offenbar ist ?? nicht nur ein Lieferant von Ersatzwerten für null, sondern auch für Fehler jeder Art. Sofern sie denn links vom ?? geschehen. Ein Funktionsaufruf, in dem eine Exception fliegt, wird nicht abgefangen.

            Rolf

            --
            sumpsi - posui - obstruxi
            1. Hi Rolf,

              Das ist die Schreibweise eines Array-Literals, das als einziges Element einen String enthält.

              Nein.

              stimmt, du hast recht. Ich habe nicht sorgfältig gelesen und die Single Quotes übersehen.

              Das glaubte ich gelesen zu haben:

              ($_POST['bla'] ?? ['blub'])
              

              Würdest du meine Aussage unter diesen Voraussetzungen als richtig gelten lasen?

              Der Term ['blub'] wäre dann und nur dann ein Array-Konstruktor, wenn links davon ein Operator stände

              Genau, und das hatte mein Eiweißcomputer auch gelesen.

              Einen schönen Tag noch
               Martin

              --
              "Formschön, wetterfest, zweckfrei, und gegen Aufpreis auch entnehmbar."
              - Loriot, Familien-Original-Benutzer
              1. Hallo Martin,

                Würdest du meine Aussage unter diesen Voraussetzungen als richtig gelten lasen?

                In dieser Form würde ich sie bestenfalls lasern.

                Aber wenn ich Dir noch ein s spendiere, können wir drüber reden 😉

                Rolf

                --
                sumpsi - posui - obstruxi
            2. Hallo Rolf,

              danke für die ausführliche Erklärung. Und Du hast recht, die erste Schreibweise kann ggf. einen Type-Error auslösen ala Fatal error: Uncaught TypeError: Cannot access offset of type string on string in.... Die 2. Schreibweise ist also tatsächlich die gesuchte Lösung gewesen.

              Jörg