bjbenderTV: Frage zur Sessions mit hidden input

Hallo alle miteinander,

ich habe folgendes Anliegen. Ich baue zurzeit auf meinem Localhost einen Onlineshop um die Abläufe eines Shops zu verstehen. Nun habe ich einen Warenkorb dort habe ich einen Button Bestellung Aufgeben. Dann wird man weiter auf eine Seite geleitet wo man seine Kontaktdaten angeben muss. Auf dieser Seite speichere ich die Produktdaten (Name, Preis, Anzahl) in einen Input hidden was dafür nicht die beste Lösung ist, da bei mehreren Artikeln im Warenkorb auf der nächsten Seite dann im input hidden nur ein Produkt vom Warenkorb angezeigt wird. Was wäre dafür eine bessere Lösung welche auch Funktioniert.

Warenkorb:

Quellcode Seite^1

Quellcode Seite3

Das Warenkorbskript kommt von Allphptricks.

Das bei dem auswählen der Anzahl der Artikel ist auch noch nicht so gut gelöst, da wenn ich die Anzahl höher mache das Formular automatisch abgeschickt wird. Das liegt an "onchange="this.form.submit()". Ich habe es dann mit "this.form.reload();" versucht was nicht zum erfolg geführt hatte.

Step1.php:

<form id="order" action="step2.php" method="post" >
<?php
    session_start();
  $anzahl = $_POST['quantity'];
  $preis  = $_POST['price'];
  $artname = $_POST['name'];
?>
<input type="text" name="Anzahl" value="<?php echo $anzahl; ?>">
<input type="text" name="Preis" value="<?php echo $preis; ?>">
<input type="text" name="Art" value="<?php echo $artname; ?>">
<input name="name"placeholder="Name" type="text" required>
<input name="prename"  placeholder="Vorname" type="text" required>
<input name="mail"placeholder="Ihre E-Mail" type="email" required>
<button type="submit">Absenden</button>

Mir ist bewusst das ich hier anstatt placeholder besser mit Label arbeiten sollte.

Ich bedanke mich schon einmal im Voraus für Tipps und Anregungen und Verbesserungsvorschläge.

Mit freundlichen Grüßen

bjbenderTV

  1. Hallo bjbenderTV,

    ich habe den Code, den Du als Text im Beitrag hattest, mal in ~~~php und ~~~ eingeschlossen. Dadurch wird kein Fließtext daraus. Mit `Backticks` markiert man Inline-Code.

    Der Auto-Submit, der beim Change des Quantity-Select erfolgt, dürfte den Zweck haben, einen Gesamtpreis zu aktualisieren. Kann man machen, muss man aber nicht, sowas wäre eher ein Fall für progressive enhancement durch JavaScript.

    Das Speichern der Artikel im Warenkorb findet normalerweise in der Session statt. Sowas ist im Code doch drin, wenn auch ggf. unvollständig. Da brauchst Du kein hidden input.

    Deinen Code habe ich allerdings nicht wirklich gelesen. Er ist mir zu gruselig formatiert, und es sind vor allem Screenshots in denen man nicht ordentlich blättern kann und die man nicht eben mal in eine lokale PHP Datei kopieren kann, um damit zu spielen. Sorry. Stell ihn irgendwo online bereit (im Zweifelsfall in dein OneDrive, wo Du eine Datei über shared link veröffentlichst, geht bestimmt. In Google Drive geht's zumindest).

    Rolf

    --
    sumpsi - posui - clusi
    1. Hallo Rolf,

      erstmal Dankeschön für deine Antwort. Ich habe den Quellcode vom Warenkorb als Antwort gepostet in dem Format was du in deiner Antwort erwähnt hast. Der Autosubmit hat den Effekt welchen du beschrieben hast. Nur wenn ich die Anzahl änder schickt er das Formular ja automatisch ab um den Preis zu aktualisieren und leitet auf die step1.php Seite weiter wo man dann die Daten eingibt. Das möchte ich eigentlich nicht so haben, da man bei mehreren Produkten im Warenkorb dann immer zurück gehen muss um die Anzahl aller Produkte zu ändern. Das input hidden Feld in step1.php ist dafür gedacht die Produkte dort zu speichern um sie dann in Step2.php mit der Session wieder abzurufen. Dies funktioniert bei einem Produkt Problemlos sobald man dann aber 2 Produkte im Warenkorb hat wird das untere Produkt im input hidden angezeigt und das obere verschwindet. Dafür ist die input hidden variante wahrscheinlich nicht gedacht dafür bräuchte ich dann halt eine andere Lösung. Ich hätte jetzt daran gedacht die Bestellung in einer Datenbank zu speichern und dann später wieder abzurufen. Vielleicht hast du ja noch eine andere Idee.

      Mit freundlichen Grüßen

      bjbenderTV

  2. <?php
    session_start();
    $status="";
    if (isset($_POST['action']) && $_POST['action']=="remove"){
    if(!empty($_SESSION["shopping_cart"])) {
            foreach($_SESSION["shopping_cart"] as $key => $value) {
                    if($_POST["code"] == $key){
                    unset($_SESSION["shopping_cart"][$key]);
                    $status = "<div class='box' style='color:red;'>
                    Produkt wurde entfernt!</div>";
                    }
                    if(empty($_SESSION["shopping_cart"]))
                    unset($_SESSION["shopping_cart"]);
                            }
                    }
    }
    
    if (isset($_POST['action']) && $_POST['action']=="change"){
      foreach($_SESSION["shopping_cart"] as &$value){
        if($value['code'] === $_POST["code"]){
            $value['quantity'] = $_POST["quantity"];
            break;
        }
    }
    
    }
    ?>
    <html>
    <head>
    <title></title>
    <link rel='stylesheet' href='css/style.css' type='text/css' media='all' />
    </head>
    <body>
    <div style="width:700px; margin:50 auto;">
    <?php
    if(!empty($_SESSION["shopping_cart"])) {
    $cart_count = count(array_keys($_SESSION["shopping_cart"]));
    ?>
    <div class="cart_div">
    <a href="cart.php">
    <img src="cart-icon.png" /> Warenkorb
    <span><?php echo $cart_count; ?></span></a>
    </div>
    <?php
    }
    ?>
    <div class="cart">
    <?php
    if(isset($_SESSION["shopping_cart"])){
        $total_price = 0;
    ?>
    <table class="table">
    <tbody>
    <tr>
    <td></td>
    <td>Produktname</td>
    <td>Anzahl</td>
    <td>Einzelpreis </td>
    <td>Gesamtpreis</td>
    </tr>
    <?php
    foreach ($_SESSION["shopping_cart"] as $product){
    ?>
    <tr>
    <td><img src='<?php echo $product["image"]; ?>' width="50" height="40" /></td>
    <td><?php echo $product["name"]; ?><br />
    <form method='post' action=''>
    <input type='hidden' name='code' value="<?php echo $product["code"]; ?>" />
    <input type='hidden' name='action' value="remove" />
    <button type='submit' class='remove'>Entfernen</button>
    </form>
    </td>
    <td>
    <form method='post' action='step1.php'>
    <input type='hidden' name='code' value="<?php echo $product["code"]; ?>" />
    <input type='hidden' name='action' value="change" />
    <select name='quantity' class='quantity' onchange="this.form.submit()">
    <option <?php if($product["quantity"]==1) echo "selected";?> value="1">1</option>
    <option <?php if($product["quantity"]==2) echo "selected";?> value="2">2</option>
    <option <?php if($product["quantity"]==3) echo "selected";?> value="3">3</option>
    <option <?php if($product["quantity"]==4) echo "selected";?> value="4">4</option>
    <option <?php if($product["quantity"]==5) echo "selected";?> value="5">5</option>
    </select>
    </td>
    <td><?php echo "€".$product["price"]; ?></td>
    <td><?php echo "€".$product["price"]*$product["quantity"]; ?></td>
    </tr>
    <?php
    $total_price += ($product["price"]*$product["quantity"]);
    }
    ?>
    <tr>
    <td colspan="5" align="right">
    <strong>Gesamtpreis: <?php echo "$".$total_price; ?></strong>
    </td>
    </tr>
    </tbody>
    </table>
    <input type ='hidden' name='name' value='<?php echo $product["name"]; ?>'>
    	<input type ='hidden' name='price' value='<?php echo "&euro;".$product["price"]*$product["quantity"]; ?>'>
    <button type='submit'>Bestellung Aufgeben</button>
    </form>
      <?php
    }else{
            echo "<h3>Ihr Warenkorb ist enthält keine Artikel!</h3>";
            }
    ?>
    </div>
    <div style="clear:both;"></div>
    <div class="message_box" style="margin:10px 0px;">
    <?php echo $status; ?>
    </div>
    </div>
    </body>
    </html>
    
    1. Hallo bjbenderTV,

      sorry wenn ich am WE relativ inaktiv bin, guck nur gerade kurz rein.

      Hinweis: die ~~~ müssen jeweils auf einer eigenen Zeile stehen. Hinter das öffnende ~~~ schreibst Du noch den Dateityp, also html, php, js oder css. Das Forum kann dann Syntax-Highlighting durchführen (tut's bei PHP gerade nicht, da muss ich nochmal nachhaken).

      Welche Datei hast Du jetzt gepostet? Ist das step1.php?

      Rolf

      --
      sumpsi - posui - clusi
      1. Hallo Rolf,

        Danke erstmal für deine Antwort. Die Datei die ich als einzelne Antwort verfasst habe ist der warenkorb. Die step1.php befindet sich in der ersten Nachricht wo auch die Screenshots zu sehen sind.

        Mit freundlichen Grüßen

        bjbenderTV

        1. Hallo bjbenderTV,

          ich bin vermutlich zu blöd. Oder das Streichen des Wohnzimmers hat mir das Hirn erweicht...

          Du hast zwei PHP Dateien? Eine, die den Warenkorb zeigt, und eine step1.php. Auf der Warenkorb-Seite ist Code, der dich beim Ändern der Bestellmenge sofort nach step1.php schießt? Stimmt das so?

          Rolf

          --
          sumpsi - posui - clusi
          1. Hallo Rolf,

            dies hast du so korrekt verstanden!

            Mit freundlichen Grüßen

            bjbenderTV

            1. Hallo bjbenderTV,

              ok, es gibt zwei Ansätze zum Problem "Mengenberechnung".

              Möglichkeit 1 ist, dass Du bei einer Änderung der Bestellmenge keinen Submit machst, sondern die Berechnung mittels JavaScript durchführst. Solange das "Gesamtpreis = Grundpreis mal Menge" ist, ist das kein Problem. Schwieriger wird es, sobald Rabattstaffeln ins Spiel kommen. Die kannst Du im JavaScript programmieren, oder Du machst einen AJAX-Request zum Server, um den Preis bestimmen zu lassen. Das ist dann für Fortgeschrittene :)

              Problem bei JavaScript Lösungen ist immer, dass ein Anwender JavaScript abgeschaltet haben kann. In dem Fall bist Du aber auch mit deiner aktuellen Lösung verloren, denn dieses "onchange=submit" setzt ja auch JavaScript voraus.

              Der allgemeine Fallback für "JavaScript ist abgeschaltet" ist, dass Du auf der Folgeseite eine Bestellübersicht anzeigst, die die korrekten und am Server berechneten Preise enthält. Diese Berechnung musst Du ohnehin ausführen, weil Du einem Rechenergebnis, das der Client Dir meldet, grundsätzlich nicht vertrauen kannst. Anwender können Dir alles mögliche senden.

              Möglichkeit 2 ist, dass Du den Warenkorb zum "Affenformular" umbaust. D.h. du submittest nicht nach step1.php, sondern immer zur Warenkorbseite. Die berechnet die Preise neu, und wenn es nur ein automatischer Postback nach Mengenänderung war, wird einfach nur der neuberechnete Warenkorb wieder angezeigt. JavaScript mit clientseitiger Neuberechnung ohne Postback wäre dann ein progressive Enhancement. Wenn die Warenkorbseite erkennt, dass der Anwender "Zur Kasse" geklickt hat, leitet sie nach step1.php weiter (über die header-Funktion: header("location:step1.php")).

              Allen Möglichkeiten ist es gemeinsam, dass die Datenhaltung des Warenkorb-Inhaltes NICHT in Hidden Fields des Browsers erfolgt. Du hast eine Session, und darin ist der Warenkorbinhalt zu speichern. Das sollte ein Array aus Bestellpositionen sein, und jede Bestellposition besteht - z.B. - aus Artikelnummer, Grundpreis und Menge. Basierend auf diesem Array baut sich der Warenkorb neu auf und basierend auf diesem Array wird auf der Folgeseite die Bestellübersicht erzeugt. Der Browser hat nur den Session-Cookie mit der Session-ID darin. Darum, dass Du den bekommst, musst Du Dich nicht kümmern, das macht PHP für Dich.

              Im Detail ist das alles nicht einfach, aber ich kann und will es Dir auch nicht vorprogrammieren.

              Rolf

              --
              sumpsi - posui - clusi
              1. Hallo Rolf,

                dankeschön für deine Ausführliche Antwort! Mit JS das ganze umzusetzen ist keine gute Idee hast du ja auch so erzählt. Mit Ajax habe ich noch nie etwas gemacht. Ich hatte noch folgende Idee die hatte ich meine ich ganz am Anfang auch geäußert. Kann ich das ganze nicht auch mit einer Datenbank abfrage lösen also das bei submit die Bestellung mit den Artikel in die Datenbank mit Preis usw. gespeichert werden und. Die Bestellung bekommt eine ID welche ich dann später auf der Step2.php wieder ausgeben lasse. Die Kontakt informationen usw. Übergebe ich der step2.php mit POST.

                EDIT: Die Idee mit dem Affenformular die du auch geäußert hattest. Wäre dann sozusagen ein Updatebutton und dann hätte ich noch ein Formular welches dann einfach nach step1 sendet

                Mit freundlichen Grüßen

                bjbenderTV

                1. Hallo bjbenderTV,

                  den Warenkorb in einer SQL Tabelle zu speichern ist eine Möglichkeit, aber nicht unbedingt sinnvoll. Es ist nämlich schon alles da, um ihn in der Session zu speichern. Du hast schon Code im Programm, womit der Warenkorb als Session abgebildet wird ($_SESSION["shopping_cart"] in deinem Warenkorb-Script vom 20.07.2019 10:11). Wenn dein Session-Handling funktioniert, steht die der Warenkorb damit in allen Scripten zur Verfügung.

                  Dein Problem ist, dass Du deinen Code nicht verstehst (weil Du ihn zusammenkopiert hast). Das musst Du ändern. Mein Problem war, dass ich deinen Code bisher nicht zu verstehen versucht habe. Das habe ich geändert 😂

                  Du musst im Warenkorb-Script nur die unterschiedlichen Aufrufmöglichkeiten unterscheiden. Das ist teilweise schon drin. Du fragst $_POST['action'] ab, um eine Löschung oder eine Mengenänderung zu erkennen. Im Warenkorb-Script werden pro Produkt zwei Mini-Forms erzeugt, die diese POSTs hervorrufen. Das zweite (für action = change) ist aber falsch, weil es Dich nach step1.php schickt. Guck Dir das Mini-Form für action = remove an. Da ist das action-Attribut des form leer, damit postet das Form auf das Script zurück, das die Seite ausgegeben hat.

                  Am Ende hast Du noch einen Submit-Button (Bestellung aufgeben), für den fehlt noch das öffnende <form> Tag. Da ist auch noch ein hidden input mit product['name'] - das ist Quatsch, weil die Produkt-Schleife vorher schon zu Ende ist. Du musst auch dort "nur" ein Form erzeugen, dass eine leere action hat, und ein hidden input hinzufügen, mit einer action wie z.B. "checkout" (zur Kasse gehen). Auf dem Server prüfst Du dann, ob überhaupt was im Warenkorb drin ist und leitest dann mit header('location:...') an step1.php weiter.

                  Rolf

                  --
                  sumpsi - posui - clusi
                  1. Hallo Rolf,

                    mit dem Code hast du sowas von recht 😂. Das wollte ich ändern und werde dies auch tuen. Du hast mir grad die Augen geöffnet 😂 Was das mit der Session angeht. Danke für die Hilfestellung!

                    Mit freundlichen Grüßen

                    bjbenderTV

                  2. Hallo Rolf,

                    da habe ich doch noch eine Frage das mit dem Warenkorb passt jetzt alles und funktioniert auch super. Die Daten werden mit $_SESSION['...'] auch über geben. Nun ist das bei der Bestellübersicht genau so wie bei den hidden inputs die ich vorher hatte. Dort wird nun nur ein Produkt angezeigt. Obwohl die Produktdaten in einem Array dem Warenkorb überreicht werden. Und die $_SESSION[''] ist das Array, da das Array in $_SESSION[''] gemergt wurde.

                    Mit freundlichen Grüßen

                    bjbenderTV

                    1. da habe ich doch noch eine Frage das mit dem Warenkorb passt jetzt alles und funktioniert auch super. Die Daten werden mit $_SESSION['...'] auch über geben. Nun ist das bei der Bestellübersicht genau so wie bei den hidden inputs die ich vorher hatte. Dort wird nun nur ein Produkt angezeigt. Obwohl die Produktdaten in einem Array dem Warenkorb überreicht werden. Und die $_SESSION[''] ist das Array, da das Array in $_SESSION[''] gemergt wurde.

                      hat wer zum oben beschriebenen Problem eine Idee oder einen Ansatz?

                      1. Hallo bjbenderTV,

                        sorry, ich hatte das Posting gar nicht als Problemmeldung identifiziert.

                        Wie sieht step1.php denn jetzt aus? Läufst Du in einer Schleife über die Einträge in $_SESSION["shopping_cart"]?

                        Rolf

                        --
                        sumpsi - posui - clusi
                        1. Hallo Rolf,

                          ich beziehe die informationen aus der Session

                          <?php
                          		foreach ($_SESSION["shopping_cart"] as $product)
                          		?>
                          		<?php echo .$product["name"]; ?> <br>
                          		<?php echo "&euro;".$product["price"]; ?> <br>
                          		<?php echo "&euro;".$product["price"]*$product["quantity"]; ?> <br>
                          		<?php echo $product["quantity"];?>
                          		<?php echo $total_price; ?>
                          

                          Da die Session ja ein Array ist habe ich diese wieder gesplittet und dann so Ausgeben lassen.

                          bjbenderTV

                          1. Hallo bjbenderTV,

                            das, was Du da gepostet hast, ist wohl nicht das, was Du laufen lässt. Denn

                             echo .$product
                            

                            ist ein Syntaxerror, damit macht das Script gar nichts. Hast Du noch mehr beim Kopieren entfernt? Zum Beispiel die geschweiften Klammern, die den foreach-Block bilden (bzw. den Doppelpunkt und das endforeach; der alternativen Syntax)?

                            Rolf

                            --
                            sumpsi - posui - clusi
                            1. Hallo Rolf,

                              der Punkt beim ersten gehört nicht dazu, da hast du natürlich recht! Die geschweiften klammern des foreachblocks hatte ich auch vergessen zu kopieren. Das Problem bleibt aber Trotzdem bestehen mir wird nur ein Produkt angezeigt obwohl ich 2 verschiedene in den Warenkorb gelegt hatte.

                              Danke für deine Hilfe schon einmal im voraus!

                              bjbenderTV

                              EDIT: Fehler gefunden hatte etwas vergessen. Funktioniert jetzt alles danke für deine Hilfe!