0

我想在我有多个where子句的地方运行搜索查询。而多个取决于用户参数。

例如,我的意思是,在我的情况下,搜索可能取决于 1 列、2 列、3 列或 6 列,并且我不想以if-elseif-else所有列概率运行语句。所以,我刚刚建立了以下功能,但我被困and在两者之间multiple column search。以下是我的代码:-

function listPlayer($player="player_guest", $group="group_guest",
$weapon="weapon_guest", $point="point_guest", $power="level_guest",
$status="status_guest") {

    $lePlayer = (isset($player) && $player != "player_guest") ?
            'player= '.$mysqli->real_escape_string($player).' and' : '';

    $leGroup = (isset($group) && $group != "group_guest") ?
            'group= '.$mysqli->real_escape_string($group).' and' : '';

    $leWeapon = (isset($weapon) && $weapon != "weapon_guest") ?
            'weapon= '.$mysqli->real_escape_string($weapon).' and' : '';

    $lePoint = (isset($point) && $point != "point_guest") ?
            'point= '.$mysqli->real_escape_string($point).' and' : '';

    $lePower = (isset($power) && $power != "level_guest") ?
            'level= '.$mysqli->real_escape_string($power).' and' : '';

    $leStatus = (isset($status) && $status != "status_guest") ?
            'status= '.$mysqli->real_escape_string($status).' and' : '';

    $query = "Select pid, name from game where {$lePlayer} {$leGroup} {$leWeapon} {$lePoint} {$lePower} {$leStatus} ";

    $runQuery = $mysqli->query($query);
}

但问题and在最后。如果我使用它们,最后我会有额外and的东西,如果我不使用它们,那又是一个错误。

有人可以帮助我修复并找到更好的方法来做到这一点。

更新:我的更新代码可以在有人需要时使用,感谢Barmar

function listPlayer($player="player_guest", $group="group_guest",
$weapon="weapon_guest", $point="point_guest", $power="level_guest",
$status="status_guest") {

    $lePlayer = (isset($player) && $player != "player_guest") ?
            'player= '.$mysqli->real_escape_string($player) : '' ;

    $leGroup = (isset($group) && $group != "group_guest") ?
            'group= '.$mysqli->real_escape_string($group) : '' ;

    $leWeapon = (isset($weapon) && $weapon != "weapon_guest") ?
            'weapon= '.$mysqli->real_escape_string($weapon) : '' ;

    $lePoint = (isset($point) && $point != "point_guest") ?
            'point= '.$mysqli->real_escape_string($point) : '' ;

    $lePower = (isset($power) && $power != "level_guest") ?
            'level= '.$mysqli->real_escape_string($power) : '' ;

    $leStatus = (isset($status) && $status != "status_guest") ?
            'status= '.$mysqli->real_escape_string($status) : '' ;

    $condition_array = ( $lePlayer , $leGroup , $leWeapon , $lePoint , $lePower , $leStatus)

    $condition_stirng = implode(' and ', $condition_array);

    $query = "Select pid, name from game where ".$condition_stirng;

    $runQuery = $mysqli->query($query);

    }

更新:

我收到了来自某人的邮件,邮件中说我的代码易受 SQL 注入攻击。这里是 POC http://www.worldofhacker.com/2013/09/interesting-sql-vulnerable-code-even.html

谢谢

4

4 回答 4

1

将所有条件放在一个数组中。然后将它们与:

$condition_string = implode(' and ', $condition_array);
于 2013-09-22T04:27:01.000 回答
0

请注意,$defaults确保您的条件有效。有点重复,但这都是由于您的函数声明。

function listPlayer(
    $player="player_guest",
    $group="group_guest",
    $weapon="weapon_guest",
    $point="point_guest",
    $power="level_guest",
    $status="status_guest") {

    //I'm just copying whatever is in the default parameters ;)
    $defaults = array(
        'player' => 'player_guest',
        'group' => 'group_guest',
        'weapon' => 'weapon_guest',
        'point' => 'point_guest',
        'power' => 'level_guest',
        'status' => 'status_guest'
    );

    //Set all user parameters into an array, easier to loop through
    $data = compact(array_flip($defaults));

    //Then we build conditions
    $conditions = array();
    foreach($data as $k => $v) {
        if ($defaults[k] !== $v) {
            $v = $mysqli->real_escape_string($v);
            $conditions[] = "$k='$v'";
        }
    }

    //And build query
    $query = "SELECT pid, name FROM game WHERE ".implode(" AND ", $conditions);
    $runQuery = $mysqli->query($query);
}
于 2013-09-22T04:36:16.050 回答
0

首先,当您在 PHP 中使用 MySQL 时,我建议您查看PDO 。

这样的任务总是用数组映射简单地解决。

function listPlayer($player = null, $group = null, $weapon = null, $point = null, $power = null, $status = null) {
    $defaults = array(
        'player' => 'player_guest',
        'group' => 'group_guest',
        'weapon' => 'weapon_guest',
        'point' => 'point_guest',
        'status' => 'status_guest',
    );
    $values = compact(array_keys($defaults));

    $filtered = array_filter(array_diff_assoc($values, $defaults)); //firstly filtering out defaults, then - nulls.

    $where = '';
    foreach($filtered as $column => $value){
        if($where){
            $where .= ' AND ';
        }
        $where .=  sprintf("`%s` = '%s'", $column, $mysqli->real_escape_string($value));
    }

    $query = "SELECT pid, name FROM game WHERE $where";
    //executing...
}
于 2013-09-22T04:36:38.260 回答
0

简单的解决方案是在最后修剪“和”:

$query = substr($query, 0, strlen($query) - 3);

然而,更有效的方法是将它们放在一个循环中,如下所示:

$wheres = array("player_guest"=>$player, "group_guest"=>$group.....);
$query_where = "";
$i = 0;
foreach($wheres as $where=>$value){
    list($condition, $null) = explode("_",$where);
    if(isset($value)){
        $query_where .= $condition . "='" . $mysqli->real_escape_string($value)."'";
        if($i != sizeof($wheres)){
            $query_where .= " and ";
        }
    }
    $i++;
}

这对于任何数量的条件都是可扩展的,并且最后不需要额外的字符串函数。

于 2013-09-22T04:23:00.977 回答