Я хочу запустить поисковый запрос, где у меня есть несколько предложений 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
в конце, и если я не буду использовать их, чтобы снова была ошибка.
Может кто-нибудь помочь мне исправить и найти лучший способ сделать это.
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 Injection. Здесь это POC http://www.worldofhacker.com/2013/09/interesting-sql-vulnerable-code-even.html
Спасибо
Поместите все условия в массив. Затем объедините их с:
$condition_string = implode(' and ', $condition_array);
Прежде всего, я рекомендую вам посмотреть PDO при работе с MySQL в PHP.
Такие задачи всегда просто решаются с помощью массивов массивов.
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...
}
Простым решением является обрезание "и" в конце:
$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++;
}
Это расширяется для любого количества условий и не требует дополнительной строковой функции в конце.
Обратите внимание, что $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);
}