Murli: Übergabe von Checkbox-Werten in die Select-Abfrage

Hallo,

ich hoffe ich stelle meine Frage so, dass man sie auch versteht ... ;-)

Mein Konstrukt funktioniert mit MySQL und Php, allerdings bin ich noch relativ frisch dabei.

Ich habe eine Nachrichtenübersicht und davor Checkboxen, sieht so aus (Schema)

[ ] Überschrift Nachricht 1 >Link zum weiterlesen
[ ] Überschrift Nachricht 2 >Link zum weiterlesen
[ ] Überschrift Nachricht 3 >Link zum weiterlesen

Bisher ist es so, dass man die Nachrichten einzeln anklicken muss. Ich möchte jedoch, dass man auch alle drei Nachrichten (oder nur 2) per Checkbox auswählen kann und dann die allesamt auf einer Seite kommen.

Die Sache mit der Übergabe der Checkbox-Häkchen funktioniert. Also wenn ich einen Haken setze, wird die ID der Nachricht übergeben. Bisher habe ich das nur probiert und die IDs werden in der Datei ausgabe.php untereinander ausgegegeben, also z.B.

9987
9988
9989

Meine Überlegung bzw. mein Ansatz ist der, dass die einzelnen Nachrichten bisher immer per ID angezeigt werden, also

  
"select * from $table WHERE id='xxx' Order By date DESC");  

Mein Problem bzw. meine Frage ist jetzt, wie ich die per Checkbox ausgewählten IDs in meine Abfrage bekomme, sodass diese z.B. so aussieht ...

  
"select * from $table WHERE id='9987' or id ='9988' Order By date DESC");  

Ich hoffe, ich habe mein Problem vernünftig dargestellt. Wenn es andere Ansätze gibt, die ich nicht erkenne oder wenn ich noch weitere Infos posten soll, dann bitte ich um eine Rückmeldung. Über Hilfe würde ich mich sehr freuen, denn an dieser Stelle hier hänge ich und komme nicht weiter.

Vielen Dank!

  1. Hi,

    Mein Problem bzw. meine Frage ist jetzt, wie ich die per Checkbox ausgewählten IDs in meine Abfrage bekomme, sodass diese z.B. so aussieht ...

    "select * from $table WHERE id='9987' or id ='9988' Order By date DESC");

      
    Lasse dir die Werte als Array übergeben (eckige Klammern an den Namen hängen, name="xyz[]"), und generiere daraus eine komma-separierte Liste, die du im IN()-Operator einsetzen kannst.  
      
    Und informiere dich über SQL Injection, und was du dagegen zu tun hast.  
      
    MfG ChrisB  
      
    
    -- 
    Light travels faster than sound - that's why most people appear bright until you hear them speak.
    
    1. Lasse dir die Werte als Array übergeben (eckige Klammern an den Namen hängen, name="xyz[]"), und generiere daraus eine komma-separierte Liste, die du im IN()-Operator einsetzen kannst.

      Danke für die schnelle Antwort. Gibt es dazu vielleicht ein Tutorial, einen (Beispiel-)Codeschnipsel oder etwas ähnliches (Links?). Die Beschreibung ist für mich wie eine Anleitung in serbokroatisch ...

      1. Hello,

        Lasse dir die Werte als Array übergeben (eckige Klammern an den Namen hängen, name="xyz[]"), und generiere daraus eine komma-separierte Liste, die du im IN()-Operator einsetzen kannst.

        Danke für die schnelle Antwort. Gibt es dazu vielleicht ein Tutorial, einen (Beispiel-)Codeschnipsel oder etwas ähnliches (Links?). Die Beschreibung ist für mich wie eine Anleitung in serbokroatisch ...

        Dann lass es uns übersetzen:

        Wie sieht das Formular aus?

        <form action="<?php echo $_SERVER['SCRIPT_NAME']; ?>" method="post" enctype="multipart/form-data">

        <p><input type="checkbox" name="ctrl[record][]" value="1234"> 1234</p>
                <p><input type="checkbox" name="ctrl[record][]" value="2345"> 2345</p>
                <p><input type="checkbox" name="ctrl[record][]" value="2222"> 2222</p>
                <p><input type="checkbox" name="ctrl[record][]" value="1313"> 1313</p>
                <p><input type="checkbox" name="ctrl[record][]" value="4711"> 4711</p>

        <p><input type="submit" name="btn[show]" value="anzeigen"></p>

        </form>

        In der PHP-Datei steht dann ungefähr:

        if (isset($_POST['btn']['show']))
           {
               if (isset($_POST['ctrl']['record']) and is_array($_POST['ctrl']['record']))
               {
                   $_liste = array_map('intval', $_POST['ctrl']['record']);
                   $liststr = "('" . implode(",'", $_liste) . "')";
               }

        ## Aufruf des SHOW-Statements

        }

        und das Statement kennst Du schon.

        Nun hoffe ich, dass kein Tippfejhler drin ist.
        Lass Dir an geeigneten Stellen einfach zur Kotrolle mal ausgegen, was in den Variablen drin steht. dann sollte es am schnellstens klar werden, was da passiert.

        Liebe Grüße aus dem schönen Oberharz

        Tom vom Berg

        --
        Nur selber lernen macht schlau
        http://bergpost.annerschbarrich.de
        1. Hello,

          $liststr = "('" . implode(",'", $_liste) . "')";

          Noch zwei Sätze dazu, warum ich mich hier für die Häkchen entschieden habe, obwohl es sich um zahlen handelt. Das hat nichts mit Doppelparanoia zu tun, sondern mit Bequemlichkeit.

          Wenn Du abfragst

          select id, zahl from zahl where id in (1,3,7,8,11);

          ist das für MySQL auch OK. Aber wenn die Liste leer ist, also dadurch dann

          select id, zahl from zahl where id in ();

          ERROR 1064 (42000): You have an error in your SQL syntax; check the manual that corresponds
              to your MySQL server for the right syntax to use near ')' at line 1

          gibt es eine hässliche Fehlermeldung, weil die Liste leer ist.

          Wenn Du nun aber

          select id, zahl from zahl where id in ('');

          abfragst, sit MySQL damit zufrieden, da die Liste nicht leer ist, sondern einen Leerstring enthält.
          Das ergibt dann einfach ein leeres Resultset

          Liebe Grüße aus dem schönen Oberharz

          Tom vom Berg

          --
          Nur selber lernen macht schlau
          http://bergpost.annerschbarrich.de
          1. ...zuerst einmal vielen Dank für die umfangreiche Hilfe. Da mein Ansatz natürlich nicht identisch war, musste ich mich erst einmal hineindenken, jetzt funktioniert es aber grundsätzlich, allerdings nur dann, wenn ich einen Haken mache. Wenn ich zwei Haken in den Checkboxen setze, kommt die Fehlermeldung

              
            You have an error in your SQL syntax; check the manual that corresponds to your MySQL server version for the right syntax to use near '9940')) AND untertext_nr=474 Order By date DESC' at line 1You have an error in your SQL syntax; check the manual that corresponds to your MySQL server version for the right syntax to use near '9940')) AND untertext_nr=475 Order By date DESC' at line 1You have an error in your SQL syntax; check the manual that corresponds to your MySQL server version for the right syntax to use near '9940')) AND untertext_nr=476 Order By date DESC' at line 1  
            
            

            So sieht die Zeile aus ...

              
            $result = mysql_query("select * from  $table WHERE untertext='2' AND id IN ($liststr) AND untertext_nr=$idd[$m] Order By date DESC");  
            
            

            Könnt Ihr mir bitte noch mal helfen?

            Vielen Dank!

            1. Hello,

              $result = mysql_query("select * from  $table WHERE untertext='2' AND id IN ($liststr) AND untertext_nr=$idd[$m] Order By date DESC");

                
              Wenn Du den $liststr so aufbauen lassen hast, wie ich es gepostet hate, dann steht er bereits in Klammern. Das geht für mich auch aus der Fehlermeldung hervor.  
                
              Bau das SQL-Query mal separat auf.  
                
                
                 $sql = "select \* from  $table ".  
                        "WHERE untertext='2' ".  
                        "AND id IN $liststr ".  
                        "AND untertext\_nr={$idd[$m]} ".  
                        "Order By date DESC";  
                
              und lasse ihn die anzeigen, bevor Du ihn an die Query-Funktion übergibst.  
                
                 echo "<p>$sql</p>";  
                
                 $result = mysql\_query ($sql, $connection);  
                
                
                
                
              Liebe Grüße aus dem schönen Oberharz  
                
                
              Tom vom Berg  
              ![](http://selfhtml.bitworks.de/Virencheck.gif)  
                
              
              -- 
              Nur selber lernen macht schlau  
              <http://bergpost.annerschbarrich.de>
              
              1. Danke, ich glaube ich weiß, wo das Problem liegt.

                Es gibt in dem Script noch mal eine separate Abfrage, d.h. es werden alle Beiträge noch mal nach einer gesonderten ID durchsucht. Aufgrund dessen durchsucht er alle untertext_nr, die einer ID zugeordnet sind (immer 8 Stück). So kommt es zu der Ausgabe ...

                  
                select * from news WHERE untertext='2' AND id IN (9944,9940) AND untertext_nr=474 Order By date DESC  
                  
                select * from news WHERE untertext='2' AND id IN (9944,9940) AND untertext_nr=475 Order By date DESC  
                  
                select * from news WHERE untertext='2' AND id IN (9944,9940) AND untertext_nr=476 Order By date DESC  
                  
                select * from news WHERE untertext='2' AND id IN (9944,9940) AND untertext_nr=477 Order By date DESC  
                  
                select * from news WHERE untertext='2' AND id IN (9944,9940) AND untertext_nr=478 Order By date DESC  
                  
                select * from news WHERE untertext='2' AND id IN (9944,9940) AND untertext_nr=479 Order By date DESC  
                  
                select * from news WHERE untertext='2' AND id IN (9944,9940) AND untertext_nr=480 Order By date DESC  
                  
                select * from news WHERE untertext='2' AND id IN (9944,9940) AND untertext_nr=481 Order By date DESC  
                
                

                Wie kann ich das denn beschränken? Ich dachte, das ginge mit LIMIT, das war aber natürlich falsch gedacht. Stehe auf dem Schlauch!

                1. ... ich glaub ich hab's, muss noch mal testen

                  1. Hallo,

                    also, es funktioniert jetzt soweit, vielen Dank noch mal!

                    Es gibt allerdings 2 Fußnoten bzw. Fragen, die ich noch habe und über deren Beantwortung ich mich freuen würde:

                    a) In der $liststr-Zeile mit den ''' gab es einen Fehler. Ich habe die '' jetzt entfernt und jetzt läuft es. Das Problem war, dass die Ausgabe so aussah:

                    (9980','9999',...)

                    also das ' vor der ersten Zahl gefehlt hat und so eine Fehlermeldung produiziert wurde.

                    b) Ist es Möglichkeit, eine "Auskunft" zu geben, wenn keine Checkbox ausgewählt wurde? Also ...

                    if { checkbox wurde nicht angeklickt
                    echo 'bitte wählen sie eine aus';
                    }

                    c) Ist in Deinem Beispiel schon eine Absicherung gegen diese Injektion drin und wenn nein, gibt es einen empfehlenswerten Link bzw. ein Beispiel zur Anwendung?

                    Das wars. Vielen Dank noch mal und ein schönes Rest-Wochenende!

                    Sascha

                    1. Hello,

                      a) In der $liststr-Zeile mit den ''' gab es einen Fehler. Ich habe die '' jetzt entfernt und jetzt läuft es. Das Problem war, dass die Ausgabe so aussah:

                      (9980','9999',...)

                      also das ' vor der ersten Zahl gefehlt hat und so eine Fehlermeldung produiziert wurde.

                      b) Ist es Möglichkeit, eine "Auskunft" zu geben, wenn keine Checkbox ausgewählt wurde? Also ...

                      Ich hatte als Code-Schnipsel vorgeschlagen:

                      Den ergänze ich un einfach durch einen else-Zweig

                      if (isset($_POST['btn']['show']))
                         {
                             if (isset($_POST['ctrl']['record']) and is_array($_POST['ctrl']['record']))
                             {
                                 $_liste = array_map('intval', $_POST['ctrl']['record']);
                                 $liststr = "('" . implode(",'", $_liste) . "')";

                      ## Aufruf des SHOW-Statements, wenn es sich nur auf die Checkboxen bezieht
                             }
                             else
                             {
                                 ## Keine Checkboxen gewählt
                                 $_output['errors'][] = 'Sie haben keine Option ausgewählt';
                             }

                      ## Aufruf des Show-Statements, wenn es außedr den Checkboxnen auch noch andere
                             ## andere Daten bereitstellen muss

                      }

                      Zur Frage mit der in()-Funktion

                      +---   den hatte ich vergessen
                                                    |
                                                    v
                         $liststr = "('" . implode("','", $_liste) . "')";
                                      ^              ^               ^
                                      |              |               |

                      Die anderen Stringbegrenzer hatte ich drin im Mustercode.
                      Sorry, den einen hatte ich vergessen.

                      Du hast ihn beim Nachbauen dafür an einer anderen Stelle unterschlagen ;-))

                      Ich würde die Stringbegrenzer aus den schon erwähnten Gründen setzen lassen und außerdem ist die Funktion dann auch schnell umgebaut, um nach echten Stringinhalten (in einer anderen Spalte) zu suchen. Da muss dann nur das intval() gegen ein mysql_real_escape_string() ausgetauscht werden.

                      Liebe Grüße aus dem schönen Oberharz

                      Tom vom Berg

                      --
                      Nur selber lernen macht schlau
                      http://bergpost.annerschbarrich.de
                      1. ...noch mal vielen Dank!

                        Ein Problem gibt es noch, wenn keine Berichte angeklickt werden. Dann erscheint folgende Meldung:

                        You have an error in your SQL syntax; check the manual that corresponds to your MySQL server version for the right syntax to use near 'AND untertext_nr=474 Order By date DESC' at line usw.

                        Wo kann da der fehler liegen?

                        Danke!

                        1. Hello,

                          Ein Problem gibt es noch, wenn keine Berichte angeklickt werden. Dann erscheint folgende Meldung:

                          You have an error in your SQL syntax; check the manual that corresponds to your MySQL server version for the right syntax to use near 'AND untertext_nr=474 Order By date DESC' at line usw.

                          Wo kann da der fehler liegen?

                          Es wäre hilfreich, das gesamte durch PHP zusammengebaute SQL-Statement zu haben.
                          Lass Dir das mal zur Kontrolle ausgeben.

                          $sql = "select $fieldlist from $table WHERE id in $liststr ...  "

                          echo $sql;

                          $res = mysql_query($sql, $con);

                          Liebe Grüße aus dem schönen Oberharz

                          Tom vom Berg

                          --
                          Nur selber lernen macht schlau
                          http://bergpost.annerschbarrich.de
                          1. Danke! Das kommt dabei raus:

                            select * from news WHERE untertext='2' AND id IN AND untertext_nr=474 Order By date DESC

                            muss da noch irgendwie eine Klammer hinter id IN? Nur noch mal zur Verdeutlichung, so sehen die wesentlichen Zeilen aus ...

                            $liststr = "('" . implode("','", $_liste) . "')";

                            ...

                            $result = mysql_query("select * from  $table WHERE untertext='2' AND id IN $liststr AND untertext_nr={$idd[$m]} Order By date DESC");

                            1. Hello,

                              select * from news WHERE untertext='2' AND id IN AND untertext_nr=474 Order By date DESC

                              muss da noch irgendwie eine Klammer hinter id IN? Nur noch mal zur Verdeutlichung, so sehen die wesentlichen Zeilen aus ...

                              $liststr = "('" . implode("','", $_liste) . "')";

                              ...

                              $result = mysql_query("select * from  $table WHERE untertext='2' AND id IN $liststr AND untertext_nr={$idd[$m]} Order By date DESC");

                              Das kann nicht sein, denn dann müsste das Statement lauten

                              select * from news WHERE untertext='2' AND id IN ('') AND untertext_nr=474 Order By date DESC

                              und das müsste dann funktionieren, also vermutlich ein leeres Resultset ergeben.

                              Da hast Du ein anderes Statement für "$liststr = ..." benutzt, als Du oben gepostet hast.

                              Liebe Grüße aus dem schönen Oberharz

                              Tom vom Berg

                              --
                              Nur selber lernen macht schlau
                              http://bergpost.annerschbarrich.de
                              1. Hi,

                                nee, das sind die beiden Zeilen ...

                                $sql = "select * from  $table WHERE untertext='2' AND id IN $liststr AND untertext_nr={$idd[$m]} Order By date DESC";

                                $liststr = "('" . implode("','", $_liste) . "')";

                                1. Hello,

                                  nee, das sind die beiden Zeilen ...

                                  $sql = "select * from  $table WHERE untertext='2' AND id IN $liststr AND untertext_nr={$idd[$m]} Order By date DESC";

                                  $liststr = "('" . implode("','", $_liste) . "')";

                                  Wo wird denn in deinem Gesamtkunstwerk $liststr erzeugt?
                                  Hast Du error_reporting(E_ALL) oben in Deinem Script drinstehen zum Debuggen?

                                  Vermutlich wird Dein $liststr gar nicht genereriert, wenn keine Treffer vorhanden sind. Dann kann er später auch nicht ins SQL-Statement eingesetzt werden.

                                  Da ist ggf. ein kleiner Designfehler in meinem Vorschlag.
                                  Wenn das Statement auch mit leerem $liststr aufgerufen werden können soll, musst Du den vorher entweder mit

                                  $liststr = "('')";

                                  setzen oder besser die Sequenzen in der Bedingung ändern:

                                  $liststr = '';

                                  if (isset($_POST['btn']['show']))
                                     {
                                         if (isset($_POST['ctrl']['record']) and is_array($_POST['ctrl']['record']))
                                         {
                                             $_liste = array_map('intval', $_POST['ctrl']['record']);
                                             $liststr = "AND id IN ('" . implode(",'", $_liste) . "')";
                                         }
                                         else
                                         {
                                             ## Keine Checkboxen gewählt
                                             $_output['errors'][] = 'Sie haben keine Option ausgewählt';
                                         }

                                  ## Aufruf des Show-Statements, wenn es außer den Checkboxen auch noch
                                         ## andere Daten bereitstellen muss

                                  $sql = "select * from  $table".
                                                " WHERE untertext='2' $liststr ".
                                                " AND untertext_nr={$idd[$m]} Order By date DESC";

                                  # ...
                                     }

                                  Bitte nur als Anregeung nehmen :-)

                                  Liebe Grüße aus dem schönen Oberharz

                                  Tom vom Berg

                                  --
                                  Nur selber lernen macht schlau
                                  http://bergpost.annerschbarrich.de
  2. Hello,

    "select * from $table WHERE id='9987' or id ='9988' Order By date DESC");

      
    Ich fange bei  Statement vorne an:  
      
       Select \*  
      
    sollte man im Produktiveinsatz nicht mehr schreiben, wenn man nicht alle Spaltenwerte benötigt, sondern nur eine geringe Auswahl daraus. Dann sollte man die Spaltennamen gezielt angeben.  
      
    Die Möglichkeit, die gewünschten Datensätze mit 'or' einzusammeln ist grundsätzlich richtig.  
    Die übergebenen IDs sollte man auf jeden Fall gegen gefakte Werte abprüfen, also sicherstellen, dass auch wirklich nur (natürliche) Zahlen übermittelt werden und keine wilden Strings (-> SQL Injection).  
      
    Das kann man z.B. mittels der PHP-Funktion intval() richtogstellen. Im Zweifelsfalle wird dann eben  
      
       intval('böser böser SQL-String')  zu 0  
      
    und 0 sollte bei vernünftiger ID-Wahl für die Tabelle einen ungültigen Index bedeuten.  
      
    Es gibt außerdem bei MySQL die Funktion in()  
      
       select $spalten from $table where id in ($idliste);  
      
    $idliste sollte dann eine durch Komma getrennte Liste von IDs sein.  
      
      
    Wenn Du die Checkboxen zu einem Checkboxarray zusammenfasst, kannst du dieses automatisch verarbeitetn lassen.  
      
    Die Funktionen array\_map(), intval() und  implode() helfen Dir dabei.  
      
      
      
      
      
      
      
    Liebe Grüße aus dem schönen Oberharz  
      
      
    Tom vom Berg  
    ![](http://selfhtml.bitworks.de/Virencheck.gif)  
      
    
    -- 
    Nur selber lernen macht schlau  
    <http://bergpost.annerschbarrich.de>