php - 如何使用多个 WHERE 条件(准备语句)参数化 SQL 查询?

php - How to parametrize SQL query with multiple WHERE conditions (prepared statement)?

我在 WHERE 子句中有多个由用户输入的条件(称它们为 过滤器)。目前我正在以这种方式处理它们(不用担心它没有部署):

//$by_nickname etc. are filters from $_GET

$conditions = array();

if($by_nickname !="")
{
    $conditions[] = " players.lastName LIKE ('%" . $by_nickname . "%')";
}

if($by_steamid !="")
{
    $conditions[] = " ids.uniqueId = '$by_steamid'";
}

if($by_ip !="")
{
    $conditions[] = " players.lastAddress = '$by_ip'";
}

if($by_msg !="")
{
    $conditions[] = " chat.message LIKE ('%" . $by_msg . "%')";
}

if (count($conditions) > 0)
{
    $where = implode(' AND ', $conditions);
    $query = "SELECT ... WHERE " . $where;
}
else
{
    $query = "SELECT ... ";
}

我会用

代替这个
$conditions[] = " ids.uniqueId = ?";

等等。现在我也将获得 $where,但使用 ? 而不是过滤器值。

现在应该准备查询

$stmt = $mysqli->prepare("SELECT ... WHERE $where");

并像这样参数化

$stmt->bind_param('ss', $by_nickname, $by_steamid);

但是,如果某些过滤器可能为空,我如何参数化查询?简单地说,我事先不知道 bind_param() 方法参数。

我已经使用具有 命名参数 的 PDO 解决了我的问题。所以这是我的解决方案,希望它能帮助别人。

$by_nickname = $_GET['nickname'];
$by_steamid = $_GET['steamid'];
// integer
$by_serverid = $_GET['serverid'];

$pdo = new PDO("mysql:host=host;port=port;dbname=db;charset=utf8", "user", "password");

$conditions = array();
$parameters = array();
$where = "";

if($by_nickname !="")
{
    $conditions[] = " players.nickname LIKE :nickname";
    $parameters[":nickname"] = "%$by_nickname%";
}

if($by_steamid !="")
{
    $conditions[] = " ids.steamid = :steamid";
    $parameters[":steamid"] = $by_steamid;
}

if($by_serverid !="")
{
    $conditions[] = " servers.serverid = :serverid";
    // Beware of correct parameter type!
    $parameters[":serverid"] = intval($by_serverid);
}

if (count($conditions) > 0)
{
    $where = implode(' AND ', $conditions);
}

// check if $where is empty string or not
$query = "SELECT ... " . ($where != "" ? " WHERE $where" : "");

try
{
    if (empty($parameters))
    {
        $result = $pdo->query($query);
    }
    else
    {
        $statement = $pdo->prepare($query);
        $statement->execute($parameters);
        if (!$statement) throw new Exception("Query execution error.");
        $result = $statement->fetchAll();
    }
}
catch(Exception $ex)
{
    echo $ex->getMessage();
}

foreach($result as $row)
{
  // for example
  echo row["<Column Name>"];
}