Enrico: Problem beim Durchlaufen eines Array

Hallo und guten Abend,

ich habe ein Problem im Umgang mit einem Array.

Ich bekomme über $_POST Werte aus einem Formular geliefert, das ich dem Array $Artikel zuordne:

  
   $Artikel = array ('Bezeichnung' => $Bezeichnung,  
                     'Groesse'     => $Groesse,  
                     'Farbe'       => $Farbe,  
                     'Anzahl'      => $Anzahl,  
                     'Einzelpreis' => $Einzelpreis);  

Nachfolgend will ich überprüfen, ob im Array $_SESSION['ID'] schon ein gleichnamiger Artikel abgelegt wurde.

Wenn ja, dann soll lediglich die Menge erhöht werden:

  
   for ($i = 0; $i < count ($_SESSION['ID']); $i++)  
   {  
----> if ($_SESSION['ID'][$i]['Bezeichnung'] == $Bezeichnung) <----  
      {  
         $_SESSION['ID'][$i]['Anzahl'] += 1;  
      }  
      else  
      {  
         $_SESSION['ID'][] = $Artikel;  
      }  
   }  

In der markierten Zeile mit dem Abgleich bekomme ich aber folgende Fehlermeldung:

Fatal error: Cannot use string offset as an array

Muss ich das Session-Array tiefer "verschachteln" oder was habe ich hier falsch gemacht?

Danke für eure Hilfe und Gruß,

Enrico

  1. Tach!

    for ($i = 0; $i < count ($_SESSION['ID']); $i++)

    foreach durchläuft ein Array, ohne dass man vorher zählen muss, wieviele Elemente es enthält. Und es können auch Lücken in den Keys enthalten sein.

    ----> if ($_SESSION['ID'][$i]['Bezeichnung'] == $Bezeichnung) <----

    In der markierten Zeile mit dem Abgleich bekomme ich aber folgende Fehlermeldung:
       Fatal error: Cannot use string offset as an array
    Muss ich das Session-Array tiefer "verschachteln" oder was habe ich hier falsch gemacht?

    Nicht raten, sondern erstmal genau nachsehen, was wirklich in dem Array steht: var_dump($_SESSION['ID'][$i]);

    Und das error_reporting beim Entwickeln auf E_ALL sowie dislay_errors auf on stellen.

    dedlfix.

    1. Hallo,

      ich denke, dass ich auf dem richtigen Weg bin.

      Nach einigen fehlerhaften Versuchen habe ich jetzt das nachfolgende Skript erstellt:

        
      <?PHP  
      session_start();  
        
         $ID = "bd57296a5fb28645ab49c303d7a7fee5";  
        
         $_SESSION['ID'] = array();  
        
         $_POST['Bezeichnung'] = "Artikel1";  
         $_POST['Anzahl']      = 2;  
         $_POST['Groesse']     = "M";  
         $_POST['Farbe']       = "Rot";  
        
         $_SESSION['ID']['Bezeichnung'] = array();  
         $_SESSION['ID']['Bezeichnung']['Anzahl']  = $_POST['Anzahl'];  
         $_SESSION['ID']['Bezeichnung']['Groesse'] = $_POST['Groesse'];  
         $_SESSION['ID']['Bezeichnung']['Farbe']   = $_POST['Farbe'];  
        
         foreach ($_SESSION['ID'] as $Schluessel => $Wert)  
         {  
            echo ("Key: "    . $Schluessel      . "<br/>\n");  
            echo ("Anzahl: " . $Wert['Anzahl']  . "<br/>\n");  
            echo ("Größe: "  . $Wert['Groesse'] . "<br/>\n");  
            echo ("Farbe: "  . $Wert['Farbe']   . "<br/>\n");  
         }  
        
         echo "<pre>";  
        
         var_dump ($_SESSION['ID']);  
        
         echo "</pre>";  
        
      ?>  
      
      

      Es läuft fehlerfrei.

      Die Festlegung der Variablen erfolgt hier nur zu Testzwecken.

      Im Browser bekomme ich bei der foreach-Schleife folgende Anzeige:

      Key:    Bezeichnung
      Anzahl: 2
      Größe:  M
      Farbe:  Rot

      var_dump liefert mir folgende Übersicht:

      array(1)
      {
         ["Bezeichnung"] => array(3)
                            {
                               ["Anzahl"]  => int(2)
                               ["Groesse"] => string(1) "M"
                               ["Farbe"]   => string(3) "Rot"
                            }
      }

      Aber irgendwie stehe ich noch gewaltig auf dem Schlauch oder habe einen Denkfehler, den ich nicht los werde.

      Als ID soll eine zuvor erstelle, hier, wie oben bereits geschrieben, aber festgelegte ID übergeben werden, als eindeutiges Kennzeichen des Session-Array

      Als Bezeichnung soll die hier festgelegte Bezeichnung "Artikel 1" das Array "einleiten" und jeweils eine eindeutige Bestellposition mit den weiteren Details Anzahl, Größe und Farbe kennzeichnen

      Wie bekomme ich das noch umgesetzt?

      Danke und Gruß,
      Enrico

      1. Tach!

        $ID = "bd57296a5fb28645ab49c303d7a7fee5";
           $_SESSION['ID'] = array();

        Deine ID steckt nun in der Variable namens $ID. Als Schlüssel nimmst du aber das String-Literal 'ID'. Das heißt, dein Schlüssel lautet ID und die Variable wird nicht benutzt. Du kannst als Key auch die Variable notieren, dann wird ihr Inhalt als Schlüssel verwendet.

        Als ID soll eine zuvor erstelle, hier, wie oben bereits geschrieben, aber festgelegte ID übergeben werden, als eindeutiges Kennzeichen des Session-Array

        Warum eigentlich? Die Session-Daten liegen je nach Session getrennt herum. Über $_SESSION hast du nur auf die Daten der einen Session zugriff, aber nicht auf die der anderen. Die Verwendung einer weiteren ID, noch dazu eine aus einem festen Wert für die gesamte Anwendung, ergibt keinen Sinn.

        Als Bezeichnung soll die hier festgelegte Bezeichnung "Artikel 1" das Array "einleiten" und jeweils eine eindeutige Bestellposition mit den weiteren Details Anzahl, Größe und Farbe kennzeichnen

        Dann nimm den Variableninhalt - sprich: gib die Variable als Key an und kein String-Literal.

        Glossar:
        Ein String-Literal ist die Schreibweise, um einen String als Code auszudrücken. 'foo' und "bar" wären String-Literale in PHP.

        dedlfix.

        1. Hallo dedlfix,

          Über $_SESSION hast du nur auf die Daten der einen Session zugriff

          Da habe ich mich dann wohl falsch ausgedrückt.

          Die ID wird über folgenden Code auf der Startseite erzeugt, da ich schon mehrfach gelesen habe, dass die IDs, die PHP erzeugt, nicht immer 100% sicher sein sollen:

            
          $chars = md5 (uniqid (mt_rand(), true));  
            
          $ID  = substr ($chars, 0, 8) . '-';  
          $ID .= substr ($chars, 8, 4) . '-';  
          $ID .= substr ($chars, 12, 4) . '-';  
          $ID .= substr ($chars, 16, 4) . '-';  
          $ID .= substr ($chars, 20, 12);  
            
          $_SESSION['ID'] = md5 (uniqid ($ID, true));  
          
          

          Mein Gedanke war dann folgender:

          1. Erzeugung der ID und Festlegung der Session mit dieser ID als Einstiegselement

          Du kannst als Key auch die Variable notieren, dann wird ihr Inhalt als Schlüssel verwendet

          D.h. ich muss dann $_SESSION[$ID] statt $_SESSION['ID'] notieren?

          2. Abgelegte Artikel mit deren Bezeichnung als Festlegung der nächsten Ebene

          Letztendlich soll pro Besucher folgende Struktur erzeugt werden:

          Besucher 1 hat sich eine Tunika ausgesucht:

            
          $_SESSION[bd57296a5fb28645ab49c303d7a7fee5][Tunika]['Anzahl']  = 1  
          $_SESSION[bd57296a5fb28645ab49c303d7a7fee5][Tunika]['Groesse'] = "M"  
          $_SESSION[bd57296a5fb28645ab49c303d7a7fee5][Tunika]['Farbe']   = "Natur"  
          
          

          Besucher 2 hat sich einen Brillenhelm ausgesucht:

            
          $_SESSION[56c28cf74ce8f33ba3a2cf8df537aef4][Brillenhelm]['Anzahl']  = 1  
          $_SESSION[56c28cf74ce8f33ba3a2cf8df537aef4][Brillenhelm]['Groesse'] = "L"  
          
          

          Gruß
          Enrico

          1. Tach!

            Über $_SESSION hast du nur auf die Daten der einen Session zugriff
            Da habe ich mich dann wohl falsch ausgedrückt.

            Oder einen Denkfehler im Konzept - vielleicht auch zusätzlich.

            Die ID wird über folgenden Code auf der Startseite erzeugt, da ich schon mehrfach gelesen habe, dass die IDs, die PHP erzeugt, nicht immer 100% sicher sein sollen:

            Du bekommst mit keiner Methode eine 100%-Sicherheit hin. "Nicht sicher" bei einer Session-ID kann nur bedeuten, dass sie zu leicht erratbar ist. Ansonsten ist mit einer ausreichend hohen Anzahl an Versuchen jede ID erratbar. Es wird nur irgendwann unwirtschaftlich, sie durchzuprobieren. (Wobei man dabei nicht immer von der Maximalzahl an Möglichkeiten ausgehen muss, rein zufällig könnte man die ID ja auch schon beim ersten Versuch erraten, wenn das auch sehr unwahrscheinlich ist.)

            Letztlich würde ich einfach auf PHP vertrauen. Dein Anwendungsfall ist anscheinend nur ein Shop und nicht Fort Knox. - Und glaub nur solchen Aussagen etwas, bei denen eine nachvollziehbare Begründung dabeisteht.

            Mein Gedanke war dann folgender:

            1. Erzeugung der ID und Festlegung der Session mit dieser ID als Einstiegselement

            Dann musst du diese ID auch als Session-ID verwenden und nicht innerhalb einer PHP-Session eine weitere ID hinzufügen. Schon ein simples foreach reicht aus, um deine in $_SESSION abgelegte ID zu finden - wenn dir jemand Code unterjubeln kann. Das bringt dir außer einer Verkomplizierung des Vorgangs keine Punkte.

            Aber angenommen, du nimmst wirklich deine neue ID als PHP-Session-ID, dann hilft die gegen außenstehende Angreifer. Wer schon im System ist, kann sich auch über Dateizugriffe im session.save_path die Daten anschauen.

            Du kannst als Key auch die Variable notieren, dann wird ihr Inhalt als Schlüssel verwendet
            D.h. ich muss dann $_SESSION[$ID] statt $_SESSION['ID'] notieren?

            Gemäß deines jetzigen Konzepts: ja.

            1. Abgelegte Artikel mit deren Bezeichnung als Festlegung der nächsten Ebene
              Letztendlich soll pro Besucher folgende Struktur erzeugt werden:

            Hier gilt daselbe Prinzip wie bei der ID.

            dedlfix.

            1. Hallo dedlfix,

              danke Dir, dann sollte ich mein Vorhaben auch fehlerfrei umsetzen können.

              Gruß
              Enrico

              1. Hallo dedlfix,

                jetzt klappt mein Testcase:

                  
                $_SESSION[$ID] = array();  
                  
                $Bezeichnung = "Artikel1";  
                $_POST['Anzahl']      = 2;  
                $_POST['Groesse']     = "M";  
                $_POST['Farbe']       = "Rot";  
                  
                $_SESSION[$ID][$Bezeichnung] = array();  
                $_SESSION[$ID][$Bezeichnung]['Anzahl']  = $_POST['Anzahl'];  
                $_SESSION[$ID][$Bezeichnung]['Groesse'] = $_POST['Groesse'];  
                $_SESSION[$ID][$Bezeichnung]['Farbe']   = $_POST['Farbe'];  
                  
                foreach ($_SESSION[$ID] as $Schluessel => $Wert)  
                {  
                   echo ("Key: "    . $Schluessel      . "<br/>\n");  
                   echo ("Anzahl: " . $Wert['Anzahl']  . "<br/>\n");  
                   echo ("Größe: "  . $Wert['Groesse'] . "<br/>\n");  
                   echo ("Farbe: "  . $Wert['Farbe']   . "<br/>\n");  
                }  
                
                

                liefert:

                Key: Artikel1
                Anzahl: 2
                Größe: M
                Farbe: Rot

                array(1) {
                  ["bd57296a5fb28645ab49c303d7a7fee5"]=>
                  array(1) {
                    ["Artikel1"]=>
                    array(3) {
                      ["Anzahl"]=>
                      int(2)
                      ["Groesse"]=>
                      string(1) "M"
                      ["Farbe"]=>
                      string(3) "Rot"
                    }
                  }
                }

                Gruß
                Enrico