1

私は現在、データベースから情報を取得し、MySQL クエリから入力されたデータ属性を含む HTML を生成する php ページを持っています。データベースは検索に使用され、検索にはさまざまなオプションがあります。

私が助けを必要としているのは、多くの変数がどのように処理されるかを整理する方法を知ることです。これは非常に大きなコードの混乱であり、すべてのコメントを付けたとしても、検索に別の変数を追加する方法を見つけようとして頭痛の種になります。

行と結果の数の LIMIT を除くすべての変数はオプションです。したがって、誰かがそれ以外のすべてを空白のままにしても、すべてのフィールドに細心の注意を払って入力した場合と同様に機能することを望みます.

これが私が持っているもので、6つの変数があります。

<?php
$product_size = "(".$_GET['size']." BETWEEN productsizeDOWN AND productsizeUP)";  // This code sets the variable to input into the MySQL string based on the URL
$product_size_check = $_GET['size'];    // the _checks check are used to see if the value is or isn't empty using if statements below
$manufacturer = $_GET['manufacturer']; 
$product_manufacterer_check = $_GET['manufacturer']; // _check
$product_invisible = "(hideproduct = '".$_GET['invisible']."')"; // Checks if product is hidden
$product_invisible_check = $_GET['invisible']; // _check
$product_instock_check = $_GET['instock']; // _check
$product_limit0 = $_GET['startat']; // This is the first number after LIMIT; the row to start in.
$product_limit1 = $_GET['results']; // This is how many results to load.

    $manufacturer_array = explode(",", $manufacturer); // The manufacturer comes in as "Nike,Addidas,Rebok" and is turned into an array
    $manufacturer_imploded = implode("' OR productmanufacturer = '", $manufacturer_array); // Puts it back together with "OR productmanufacturer =" between each name.
    $product_manufacterer = ("(productmanufacturer = '".$manufacturer_imploded."')"); // formats it so it can be directly inserted into MySQL string with a WHERE in front.

if($product_invisible_check == ""){
    $product_invisible = "";
}else{$where = "WHERE ";};  //Useless code that I havn't deleted that I tried to use when I searched the entire database
if($product_size_check == ""){
    $product_size = "";
}else{$where = "WHERE ";};
if($product_manufacterer_check == ""){
    $product_manufacterer = "";
}else{$where = "WHERE ";};
if($product_instock_check == "N"){ 
    $product_instock = "(stockstatus <= '0' AND donotallowbackorders = 'Y') AND "; // Checks if product is in stock (Allowing backordering OR stock >1)
    $where = "WHERE ";
}
elseif($product_instock_check == "Y") {
    $product_instock = "(stockstatus > '0' OR donotallowbackorders = 'N') AND ";
    $where = "WHERE ";
}
else {
    $product_instock = "";
};

$sql="Select * FROM ioa7pd_Products WHERE ".$product_instock.$product_size."AND".$product_manufacterer_and.$product_manufacterer."".$product_invisible." LIMIT ".$product_limit0.", ".$product_limit1; // The end result of it all. 
echo $sql;
    ?>

URLが

test.php?size=5&manufacturer=Nike,Addidas,Rebok&invisible=N&instock=Y&startat=0&results=30

結果のSQLクエリは

Select * FROM ioa7pd_Products WHERE (stockstatus > '0' OR donotallowbackorders = 'N') AND (5 BETWEEN productsizeDOWN AND productsizeUP)AND(productmanufacturer = 'Nike' OR productmanufacturer = 'Addidas' OR productmanufacturer = 'Rebok')(hideproduct = 'N') LIMIT 0, 30

しかし、検索にさらにオプションを追加する予定です。

私の主な質問は単純です:これを整理して、変数を簡単に追加できるようにするにはどうすればよいですか? 階層化された if ステートメント?

Travesty はコードの作成を手伝ってくれて、コードを整理するのに非常に役立ちました。

これが現在のコードです。注射を防ぐために安全である必要があります。

// Database connection
$con = mysql_connect("[CENSORED]","[CENSORED]","[CENSORED]")

    or die("Could not connect: " . mysql_error());


mysql_select_db("[CENSORED]") or die('Could not select database');


// Begin organization of URL variables into MYSQL Query
$get_size = $_GET['size'];
$get_manufacturer = $_GET['manufacturer'];
$get_invisible = $_GET['invisible'];
$get_instock = $_GET['instock'];
$get_sex = $_GET['sex'];
$get_startat = $_GET['startat'];
$get_results = $_GET['results'];

if ($get_size != ""){
    $all_selectors[] = "(".$get_size." BETWEEN productsizeDOWN AND productsizeUP)"; // Add to array if size is not blank.
};

if ($get_manufacturer != ""){
    $manufacturer_exploded = explode(",", $get_manufacturer);
    $manufacturer_imploded = implode("' OR productmanufacturer = '", $manufacturer_exploded);
    $all_selectors[] = ("(productmanufacturer = '".$manufacturer_imploded."')");
};

if ($get_invisible != ""){
    $all_selectors[] = "(hideproduct = '".$get_invisible."')";
};

if($get_instock == "N" or $get_instock == "n"){
    $all_selectors[] = "(stockstatus <= '0' AND donotallowbackorders = 'Y')";
}elseif($get_instock == "Y" or $get_instock == "y") {
    $all_selectors[] = "(stockstatus > '0' OR donotallowbackorders = 'N')";
};

if ($get_startat != "" or $get_results != ""){
    $number_results = "LIMIT ".$get_startat.", ".$get_results;
} else {
    $number_results = "LIMIT 0, 15";
};

// All variables are now in an array, except "startat" and "results"
$all_selectors0 = "WHERE ".implode(" AND ", $all_selectors);

// Create SQL query

$sql="Select * FROM sadsads_Products ".$all_selectors0." ".$number_results;
4

2 に答える 2

1

私はもっ​​とこのようなことをします。これはテストされておらず、おそらく 100% 完全ではありません...特にステートメントに特殊なケースを追加する場合は、さらにカスタマイズする必要があるかもしれませんがswitch、これにより、より多くの変数を簡単に追加できるようになります。

古い例を削除しました。以下の更新された例を参照してください

注意すべき重要な点の 1 つは、データベースの入力をサニタイズしていないことです。コードは SQL インジェクションに対して脆弱です。上記の例はそれを解決するのに役立ちますが、このコードは完全にはテストされていないため、クエリで使用する前にすべてのユーザー入力がサニタイズされていることを確認する必要があります。


フィールド名が MySQL 列と一致しない場合 (一致していないように見えます)、連想配列で修正できます。

$columns = array(
    // [form field] => [mysql column]
    'size' => 'product_size',
    'manufacturer' => 'product_manufacturer',
    'invisible' => 'hideproduct'
    // ...
);

そして、switchステートメントで、次のようにします。

$whereClause[] = "{$columns[$key]} = '{$value}'";

最終更新:

文書化されたサンプル - Codepadで動作させるためのコメントと追加のものがたくさんあります

正確な動作コード- これをコピーして貼り付ける (および DB 資格情報を追加する) ことができ、動作するはずです。

$con = mysqli_connect("[CENSORED]", "[CENSORED]", "[CENSORED]") or die("Could not connect: ". mysqli_error());
mysqli_select_db("[CENSORED]") or die("Could not select database");

$columns = array(
    'size' => 'product_size',
    'manufacturer' => 'product_manufacturer',
    'invisible' => 'hideproduct'
);

$whereClause = array();
$limit = array("startat" => 0, "results" => 15);

foreach ($_GET as $key=>$value) {
    $key = mysqli_real_escape_string($key);
    if (is_array($value)) {
        for ($i = 0; $i < count($value); $i++) {
            $value[$i] = mysqli_real_escape_string($value[$i]);
        }
    } else {
        $value = mysqli_real_escape_string($value);
    }

    switch ($key) {
        case 'size':
            $whereClause[] = "({$value} BETWEEN productsizeDOWN AND productsizeUP)";
            break;
        case 'startat':
        case 'results':
            $limit[$key] = $value;
            break;
        case 'instock':
            $whereClause[] = "(stockstatus ". ($value == 'N' ? "<=" : ">") ." '0' ". ($value == 'N' ? "AND" : "OR") ." donotallowbackorders = '". ($value == 'N' ? "Y" : "N") ."')";
            break;
        default: {
            if (is_array($value)) {
                $whereClause[] = "{$columns[$key]} IN ('". implode("', '", $value) ."')";
            } else {
                $whereClause[] = "{$columns[$key]} = '{$value}'";
            }
        }
    }
}

$sql = "SELECT * FROM ioa7pd_Products". (empty($whereClause) ? "" : " WHERE ". implode(" AND ", $whereClause)) ." LIMIT {$limit['startat']}, {$limit['results']}";
echo $sql;
于 2012-09-25T15:28:29.857 に答える