SQL Statement um bestimmte Werte zu erhalten

impe

Grünschnabel
Hallo,

ich bin mir nicht sicher ob ich hier richtig bin oder eher ins "relationelle Datenbanksysteme" Unterforum schreiben sollte - verzeiht sollte es hier im PHP Forum falsch sein.


Vorab - ich bin kein SQL Guru und tue mir seit einigen Stunden mit folgendem Sachverhalt ziemlich schwer.

Folgendes Szenario habe ich:
Tabelle: "favcolor" sieht so aus

User |Red |Blue |Yellow |Green |Black
Klaus|0 |1 |1 |0 |0
Jessy |1 |0 |1 |0 |1
Andy |1 |1 |0 |0 |0
Alex |0 |0 |0 |1 |1
Denis|1 |1 |0 |0 |1



Der HTML Code:
<form method="post"action="./usercolor.php">
<input type="checkbox" id="colorred" name="colorred" value="1"/>red</td>
<input type="checkbox" id="colorblue" name="colorblue" value="1"/>blue</td>
<input type="checkbox" id="coloryellow" name="coloryellow" value="1"/>yellow</td>
<input type="checkbox" id="colorgreen" name="colorgreen" value="1"/>green</td>
<input type="checkbox" id="colorblack" name="colorblack" value="1"/>black</td>
<input type="submit" value="SEARCH"/>
</form>


PHP/SQL (using MySQL 5.6):
$colorred = $_POST["colorred"];
$colorblue = $_POST["colorblue"];
$colorgreen = $_POST["colorgreen"];
$coloryellow = $_POST["coloryellow"];
$colorblack = $_POST["colorblack"];

SELECT * FROM favcolor WHERE red ='".$colorred."' AND blue ='".$colorblue."' AND green ='".$colorgreen."' AND yellow ='".$coloryellow."' AND black ='".$colorblack."'

Nun zu meinem Problem.
Ich wähle zB. die gelbe Farbe in der Checkbox aus und drücke "Suchen". Nun hätte ich gerne die Ergebnisse angezeigt, wer die gelbe Farbe mag.

Aber ich erhalte keine Ergebnisse, aufgrund des "AND" Operators im SQL Statement.
Obwohl ja in der Tabelle 2 Datenzeilen betroffen sind.
Nun bin ich mit SQL nicht lange vertraut... welchen Operator müsste ich verwenden, bzw. wie müsste ich den SQL Statement umbauen damit das funktioniert?

Hoffe Ihr könnt mir ein paar Tipps und bedanke mich vorab
 
Hi Impe.

Zunächst nutze bitte das nächstemal die Code-Tags für eine bessere Lesbarkeit hier im Forum.
2. niemals Werte direkt aus dem Post/Get in Queries übergeben sonst gehört dir die Datenbank vielleicht nicht mehr lange ;)
( entweder Prepared Statements nutzen oder die Werte zumindest Escapen )
3. Du suchst mit dem Query so nach einer Zeile, in der die Werte genauso existieren ( also umständen keine einzigste )

Eine Möglichkeit wäre das hier
PHP:
 $COLORS = array( );
if( isset( $_POST["colorred"] ) )  $COLORS['red'] = "red = 1";
if( isset( $_POST["colorblue"] ) )  $COLORS['blue'] = "blue = 1";
if( isset( $_POST["colorgreen"] ) )  $COLORS['green'] = "green = 1";
if( isset( $_POST["coloryellow"] ) )  $COLORS['yellow'] = "yellow = 1";
if( isset( $_POST["colorblack"] ) )  $COLORS['black'] = "black = 1";

$where = implode(  ' or ', $COLORS );
$sql = 'SELECT * FROM favcolor WHERE ' . $where;
 
Hallo Merzi,

danke für deine Tipps!
Dein Vorschlag klappt :)

Zu 1:
Werde ich in Zukunft machen. Habe auf den ersten Blick nicht gesehen dass unter "Einfügen... -> sich der 'Code'" versteckt

Zu 2:
Ich binde mir meine "config.php" in jede Datei ein per
HTML:
<?php require_once("../config.php");?>

In dieser Datei ist eine "Firewall" welches ich aus einem Youtube Tutorial habe
PHP:
# immer wenn etwas gepostet via '$_POST' - (alle Werte die von außen kommen durchlaufen diese Validätsprüfung)
if($_POST){
   
    # hier werden alle Posts in einer foreach Schleife abgefragt
    foreach($_POST as $key=>$val){
        # hier werden die Posts mit der 'mysql_escape_string' Prozedur 'überschrieben'
        $_POST[$key] = mysql_escape_string($val);     
       
        # Schutz vor XSS (CrossSiteScripting)
        # stripos: überprüft ob ein bestimmter String innerhalb des Strings vorhanden ist
        if(     stripos($_POST[$key], "<script") !== FALSE
            or  stripos($_POST[$key], "<iframe") !== FALSE
            or  stripos($_POST[$key], "<href") !== FALSE
            or  stripos($_POST[$key], "<img") !== FALSE
            or  stripos($_POST[$key], "<form") !== FALSE
            or  stripos($_POST[$key], "<object") !== FALSE
            or  stripos($_POST[$key], "<applet") !== FALSE
            or  stripos($_POST[$key], "<embed") !== FALSE ) {
           
            die("dies ist eine XSS Attacke!");
           
        }       
    }
}



Eine weitere Frage hätte ich noch....
Wie ist es wenn ich im HTML Code zu den Checkboxen zusätzlich noch eine (oder mehrere) Select Box(en) habe?
(in der selben Tabelle "favcolor" gibt es eine Spalte "potation", darin soll die ID der Limonade stehen)

Bsp:
Code:
</select name="limonade">
    <option value="1">Cola</option>
    <option value="2">Fanta</option>
    <option value="3">Mezzo</option>
    <option value="4">Sprite</option>
    <option value="5">Energy</option>
</select>
 
Wenn du das mit der "Firewall" machst ist das schon mal eine Möglichkeit, allerdings nutzt du da mysql_escape_string, diese Funktion ist zusammen mit allen anderen mysql_* Funktionen als Deprecated markiert und werden demnächst ( in zukünftigen PHP-Versionen ) entfernt.

Entweder nutze die mysqli_* Funktionen ( bzw. die Mysqli-Klasse ) oder PDO.

Zu deiner Frage:
Willst du dann die Datenbank einträge haben, wo die Farbe UND die "potation" so gesetzt sind oder in der Richtung entweder Farbe ODER Potation?
 
Danke für den Hinweis - dann werde ich mich nach der mysqli Klasse umsehen.

Ich würde gerne einen SQL Statement absetzen wo die Farbe UND die "potation" gesetzt ist. (Nur die potation wird halt aus einer SelectBox ausgewählt und diese SelectBox hat mehrere Werte... nicht nur 0 und 1 wie bei den Checkboxen)
 
Basierend auf dem 1. Code
PHP:
$COLORS = array( );
if( isset( $_POST["colorred"] ) ) $COLORS['red'] = "red = 1";
if( isset( $_POST["colorblue"] ) ) $COLORS['blue'] = "blue = 1";
if( isset( $_POST["colorgreen"] ) ) $COLORS['green'] = "green = 1";
if( isset( $_POST["coloryellow"] ) ) $COLORS['yellow'] = "yellow = 1";
if( isset( $_POST["colorblack"] ) ) $COLORS['black'] = "black = 1";

$where = implode( ' or ', $COLORS );
$sql  = 'SELECT * FROM favcolor WHERE (' . $where . ' )';
if( $_POST["limonade"] > 0 ) $sql .= ' and potation = ' . $_POST["limonade"];
 
@alxy
Danke für den Hinweis.
Kannst du mir erklären unter welchen Umständen die Firewall meine Eingaben zerstören soll?
Bitte nicht zu komplex erklären - ich bin noch Anfänger und habe wenig PHP Erfahrung.



@merzi86
Danke für deine Hilfe. Dein Code funktioniert.
Allerdings komme ich mit mehreren SelectBoxen an meine Grenzen...


1. Wenn ich keine Checkbox ausgewählt habe, sondern in 2 Selectboxen etwas ausgewählt habe, erhalte ich ein PHP Error, da der SQL so aussieht:
SQL:
SELECT * FROM favcolor WHERE pot1= 3 pot2= 2


2. In der Tabelle "favcolor" gibt es die 4 Spalten "pot1", "pot2", "pot3", "pot4". In diesen Spalten ist eine ID eines Getränks enthalten.
Bsp:
Der User wählt in der Selectbox1 ("limonade") das Getränk: Energy / value="5"
In der Selectbox2 ("limonade2") das Getränk: Mezzo / value="3"
Dh. es wird folgender SQL Statement zusammengesetzt: "SELECT * FROM favcolor WHERE pot1= 5 pot2= 3" - und liefert zB. 15 Treffer.

Wenn der User nun in der Selectbox1 ("limonade") das Getränk: Mezzo / value="3" und
in der Selectbox2 ("limonade2") das Getränk: Energy / value="5" auswählt,
wird dieser SQL Statement zusammengesetzt: "SELECT * FROM favcolor WHERE pot1= 3 pot2= 5" - und liefert zB. 7 Treffer.

In diesem Fall hätte ich gerne alle Treffer wo "Energy" und "Mezzo" vorkommt, unabhängig ob diese in pot1, pot2, pot3 oder pot4 vorkommen.
Ich hoffe Ihr könnt mir besonders bei Punkt 2 weiterhelfen, ich wüsste nicht wo bzw. wie ich in diesem Fall ansetzen soll :/



Nochmal zum Überblick der aktuelle Code:
HTML:
<form method="post"action="./usercolor.php">
   
<input type="checkbox" id="colorred" name="colorred" value="1"/>red</td>
<input type="checkbox" id="colorblue" name="colorblue" value="1"/>blue</td>
<input type="checkbox" id="coloryellow" name="coloryellow" value="1"/>yellow</td>
<input type="checkbox" id="colorgreen" name="colorgreen" value="1"/>green</td>
<input type="checkbox" id="colorblack" name="colorblack" value="1"/>black</td>

</select name="limonade">
    <option value="1">Cola</option>
    <option value="2">Fanta</option>
    <option value="3">Mezzo</option>
    <option value="4">Sprite</option>
    <option value="5">Energy</option>
</select>
</select name="limonade2">
    <option value="1">Cola</option>
    <option value="2">Fanta</option>
    <option value="3">Mezzo</option>
    <option value="4">Sprite</option>
    <option value="5">Energy</option>
</select>
</select name="limonade3">
    <option value="1">Cola</option>
    <option value="2">Fanta</option>
    <option value="3">Mezzo</option>
    <option value="4">Sprite</option>
    <option value="5">Energy</option>
</select>
</select name="limonade4">
    <option value="1">Cola</option>
    <option value="2">Fanta</option>
    <option value="3">Mezzo</option>
    <option value="4">Sprite</option>
    <option value="5">Energy</option>
</select>

<input type="submit" value="SEARCH"/>

</form>


PHP:
// Einlesen der Werte der Checkboxen
$whereArr = Array();
if (isset($_POST["colorred"]) && $_POST["colorred"]==1) $whereArr[] = "red=1";
if (isset($_POST["colorblue"]) && $_POST["colorblue"]==1) $whereArr[] = "blue=1";
if (isset($_POST["colorgreen"]) && $_POST["colorgreen"]==1) $whereArr[] = "green=1";
if (isset($_POST["coloryellow"]) && $_POST["coloryellow"]==1) $whereArr[] = "yellow=1";
if (isset($_POST["colorblack"]) && $_POST["colorblack"]==1) $whereArr[] = "black=1";

// SQL Statement vorbereiten mit den Value's der Checkboxen
$sql = "SELECT * FROM favcolor WHERE " . implode(" AND ", $whereArr);

// Einlesen der Werte der SelectBoxen und anhängen an den SQL Statement
if (empty($whereArr)) {   
    if( $_POST["limonade"] > 0 ) $sql .= ' pot1 = ' . $_POST["limonade"];
    if( $_POST["limonade2"] > 0 ) $sql .= ' pot2 = ' . $_POST["limonade2"];
    if( $_POST["limonade3"] > 0 ) $sql .= ' pot3 = ' . $_POST["limonade3"];
    if( $_POST["limonade4"] > 0 ) $sql .= ' pot4 = ' . $_POST["limonade4"];  
}
else {   
    if( $_POST["limonade"] > 0 ) $sql .= ' and pot1 = ' . $_POST["limonade"];
    if( $_POST["limonade2"] > 0 ) $sql .= ' and pot2 = ' . $_POST["limonade2"];
    if( $_POST["limonade3"] > 0 ) $sql .= ' and pot3 = ' . $_POST["limonade3"];
    if( $_POST["limonade4"] > 0 ) $sql .= ' and pot4 = ' . $_POST["limonade4"];   
}

echo "Abfrage2: ", $sql, "<br>";
 
das Problem ist, das du so ein Query zusammenbaust, der nicht Funktionieren kann.
Zwischen den pot1, pot2, pot3, pot4 müssen Verknüpfungsoperatoren stehen ( and, or .... ).

Ich würde dir empfehlen eigne dir mal die Mysql/Php Grundlagen an.
Sehr empfehlen kann ich da nur tut.php-quake.net.
 
Zur Firewall (der Name ist auch ein wenig "komisch"):
Die escaped erstmal generell alle Variablen im POST Array mit mysql_escape_string() - selbst, wenn die Daten garnicht für die Datenbank vorgesehen sind. Damit zerstörst du dir unter Umständen schon die Daten, etwa dann, wenn sie Anführungszeichen (", ') enthalten.
Danach kommt dann der primitivste XSS Schutz den ich je gesehen habe. Weißt du eigentlich, wie ein Angriff über XSS funktioniert? Es ist nämlich überhuapt garkein Problem, HTML, CSS oder JS Code in der Datenbank stehen zu haben - das ist auch nicht gefährlich! Gefährlich wirds, wenn beliebiger eingegebener Text (zB HTML) wieder ausgegeben wird, ohne ihn vorher zu filtern. Allerdings gibt es hunderte weitere Möglichkeiten für einen solchen Angirff als die 7-8, die du oben filterst (siehe: https://www.owasp.org/index.php/XSS_Filter_Evasion_Cheat_Sheet ).
Die Alternative dazu ist das ein wenig zu Trennen und Ausgaben etwa erst hiermit zu escapen: http://php.net/manual/de/function.htmlentities.php
Damit werden alle HTML Tags entsprechend escaped (Man muss allerdings noch ein bisschen auf Kodierung etc achten, aber ich denke mal, das würde erstmal zu weit führen.)
 
Zurück