PHP MySQL GET代码审核

时间:2018-01-13 08:28:57

标签: php mysql performance oop get

我认为这是一个非常简单的问题。这是我最好的选择,还是有“正确”的方式来做这件事?

<?php  
    $correctOrder = array("name", "address", "phone", "starttime", "endtime", 
                    "status", "details");  

    $sql->sql1 = "SELECT * FROM `pickups` WHERE";  

    if (isset($_GET["name"])){  
        $sql->sql2 = "`name` LIKE '%" . $_GET['name'] . "%'";  
        }  
    if (isset($_GET["address"])){  
        if (!isset($_GET['name'])){
            $q = "`address` LIKE '%" . $_GET['address'] . "%'";  
        } else {  
            $q = "AND `address` LIKE '%" . $_GET['address'] . "%'";  
            }
        $sql->sql3 = $q;
        }
    ...
    ...

    echo implode(" ", (array) $sql);  
?>  

所以,现在:

?name=Jari%20Martikainen&address=some%20random%20street

?name=Jari%20Martikainen&address=some%20random%20street&blah=har

?address=some%20random%20street&blah=har&name=Jari%20Martikainen

都会返回所需的相同结果,但它似乎不是一种非常有效的处理方式。

3 个答案:

答案 0 :(得分:1)

此代码使用数组来计算出它感兴趣的参数,并构建where子句数组。

我在此数组("name" => "name")中使用$correctOrder的原因是它允许参数名称和列名称不同。您应该在此处添加所需的任何参数。

此代码也使用绑定变量,不确定您使用的数据库访问的风格,但您可以将$data数组传递给execute以绑定它们。

$correctOrder = array("name" => "name", "address" => "address");

$_GET = [ 'name' => 'name1', 'address' => 'add'];

$where = [];
$data = [];
foreach ( $_GET as $paramName => $param ) {
    if ( isset($correctOrder[$paramName]) ) {
        $where[] = "`{$correctOrder[$paramName]}` like ? ";
        $data[] = '%'.$param.'%';
    }
}

$sql = "SELECT * FROM `pickups`";
if ( count($where) > 0 ){
    $sql .= " WHERE ".implode( " and ", $where);
}

echo $sql.PHP_EOL;
print_r($data);

如果有要添加的内容,count($where) > 0部分将只添加where子句,并且内部添加适当的and位作为粘合剂。

哪个测试数据给出了......

SELECT * FROM `pickups` WHERE `name` like ?  and `address` like ? 
Array
(
    [0] => %name1%
    [1] => %add%
)

这只适用于字符串,但您可以为其他数据字段添加特定代码,并在到达构建语句的最终部分之前将该子句添加到$where数组中。

答案 1 :(得分:1)

构建一个AND子句的数组($ands),但没有&#34; AND&#34;。

$ands = array();
if (...)
    $ands[] = "name LIKE ...";
if (...)
    $ands[] = "address LIKE ...";
...

然后构建查询:

$query = "SELECT ... WHERE " . implode(' AND ', $ands);

我发现这种模式简单,干净,避免像1=1这样的kludges或删除额外的AND

答案 2 :(得分:0)

这比你要求的更多一次大修。

首先,使用1 = 1启动WHERE子句,然后遍历搜索项数组,并扩展where子句(如果$ _GET数组中包含任何子句)。

其次,我使用PDO对象连接到您的数据库,然后BIND $ _GET值。这将有助于保护您免受SQL注入/黑客攻击。

下面,我循环搜索条件,如果$ _GET数组中存在某些内容,则将它们保存到名为$ sqlParams的数组中。然后我循环遍历$ sqlParams并绑定值。

// connect to database via PDO
try {
    $db = new PDO($dsn, $username, $password, $options);    
} catch (PDOException $e) {
    echo 'Connection failed: ' . $e->getMessage();
}

$correctOrder = array("name", "address", "phone", "starttime", "endtime", 
                "status", "details");  

$sql = "SELECT * FROM `pickups` WHERE 1=1 ";  

// check the $_GET array, build SQL, remember values in $sqlParams
$sqlParams = [];
foreach ($correctOrder as $key) {
    if (isset($_GET[$key])) {
        $sql .= "and `$key` LIKE :$key ";
        $sqlParams[":$key"] = "%{$_GET[$key]}%";
    }
}


// bind values from $sqlParams into SQL statement
$stmt = $db->prepare($sql);
foreach ($sqlParams as $key => &$value) {
    $stmt->bindParam($key, $value);
}

// execute SQL statement, catching exception
try {
    $stmt->execute();
} catch (PDOException $e) {
    echo 'Connection failed: ' . $e->getMessage();
}

// cycle through results and do stuff
while ($row = $stmt->fetch()) {
    print_r($row);
}