Готовая выписка, когда не знаешь, сколько параметров - PullRequest
2 голосов
/ 22 января 2020

Я пытаюсь преобразовать сложный php файл, который я сделал за год go, в подготовленные заявления. Параметры будут передаваться следующим образом:

file.php?name=John&age=20

Однако может быть гораздо больше параметров, которые могут быть использованы. работа, адрес, телефон, et c et c. Вот где я, как правило, путаюсь с подготовленными утверждениями.

Например:

$query = "SELECT name, id, age, address, phone_number from person_db WHERE 1=1 ";

if (isset($_REQUEST['name'])) {
   $query  .= " and name = ?";
}

if (isset($_REQUEST['age'])) {
   $query  .= " and age = ?";
}

if (isset($_REQUEST['address'])) {
   $query  .= " and address = ?";
}

$stmt = $db->prepare($query);
$stmt->bind_param('sis', $_REQUEST['name'], $_REQUEST['age'], $_REQUEST['address']);
$stmt->execute();

Проблема здесь bind_param, потому что я не знаю, сколько параметров потенциально может быть доступно ,

Как бы я go сказал об этом логичным образом?

Ответы [ 3 ]

2 голосов
/ 22 января 2020

Очень хороший вопрос. И решение очень простое.

То, что вам нужно, называется оператор распаковки аргумента . Это позволит вам использовать массив произвольной длины с bind_param. Все, что вам нужно, это собрать принятые параметры в массив, затем динамически создать строку типов и, наконец, использовать вышеупомянутый оператор:

$query = "SELECT name, id, age, address, phone_number from person_db WHERE 1=1 ";
$params = array();

if (isset($_REQUEST['name'])) {
   $query  .= " and name = ?";
   $params[] = $_REQUEST['name'];
}

if (isset($_REQUEST['age'])) {
   $query  .= " and age = ?";
   $params[] = $_REQUEST['age'];
}

if (isset($_REQUEST['address'])) {
   $query  .= " and address = ?";
   $params[] = $_REQUEST['address'];
}

if ($params)
    $stmt = $db->prepare($query);
    $types = str_repeat("s", count($params));
    $stmt->bind_param($types, ...$params);
    $stmt->execute();
    $result = $stmt->get_result();
} else {
    $result = $db->query($query);
}
1 голос
/ 22 января 2020

Для запроса на выбор, я не думаю, что вам нужно получить все параметры, для перечисления будет достаточно получить идентификатор, имя или имя задания, я имею в виду один параметр, может быть два.

, но при вставке такого количества значений будет очень больно , Я бы использовал такую ​​функцию:

Эта функция подсчитывает значения в массиве и привязке.

function bindQueryParams($sql, $param_type, $param_value_array) {
    $param_value_reference[] = & $param_type;
    for($i=0; $i<count($param_value_array); $i++) {
        $param_value_reference[] = & $param_value_array[$i];
    }
    call_user_func_array(array(
        $sql,
        'bind_param'
    ), $param_value_reference);
}

Эта функция вставляет:

function insert($query, $param_type, $param_value_array) {
    $sql = $this->conn->prepare($query);
    $this->bindQueryParams($sql, $param_type, $param_value_array);
    $sql->execute();
}

Использование:

 $query = "INSERT INTO tbl_token_auth (username, password_hash, selector_hash, expiry_date) values (?, ?, ?,?)";
        $result = insert($query, 'ssss', array($username, $random_password_hash, $random_selector_hash, $expiry_date));

ОБНОВЛЕНИЕ: Моя функция может быть использована для выбора следующим образом:

function runQuery($query, $param_type, $param_value_array) {

    $sql = $this->conn->prepare($query);
  //This function calling bindQueryParams function and auto creating binds
    $this->bindQueryParams($sql, $param_type, $param_value_array);
    $sql->execute();
    $result = $sql->get_result();

    if ($result->num_rows > 0) {
        while($row = $result->fetch_assoc()) {
            $results[] = $row;
        }
    }

    if(!empty($results)) {
        return $results;
    }
}

Использование:

 $query = "Select * from your table where name = ?";
  //You just need to variables in array 
 $result = runQuery($query, 's', array($your_variables));
0 голосов
/ 22 января 2020

Ну, процесс будет очень похож на то, как вы создаете переменную $query - т.е. вы добавляете в список параметров по одному.

Учтите, что bind_param требует двух вещей:

Первый - это список типов данных в виде простой строки. Таким образом, вы можете просто иметь строковую переменную, которую вы добавляете для каждого параметра, а затем передавать ее в конце bind_param.

Второй - список параметров. Это сложнее, потому что вы не можете просто предоставить массив для bind_param. Однако вы можете создать собственный массив, а затем использовать call_user_func_array , чтобы преобразовать его в плоский список.

Вот тот, который я написал ранее (и работает хорошо). Обратите внимание, что он пытается определить типы параметров и создать подходящую строку, но вы можете просто создать строку вручную в ваших операторах if, если хотите:

$query = "SELECT name, id, age, address, phone_number from person_db WHERE 1=1 ";
$params = array();

if (isset($_REQUEST['name'])) {
   $query  .= " and name = ?";
   $params[] = $_REQUEST['name'];
}

if (isset($_REQUEST['age'])) {
   $query  .= " and age = ?";
   $params[] = $_REQUEST['age'];
}

if (isset($_REQUEST['address'])) {
   $query  .= " and address = ?";
   $params[] = $_REQUEST['address'];
}

$stmt = $db->prepare($query);

if (!is_null($params))
{
  $paramTypes = "";

  foreach ($params as $param)
  {
    $paramTypes .= mysqliContentType($param);
  }

  $bindParamArgs = array_merge(array($paramTypes), $params);

  //call bind_param using an unpredictable number of parameters
  call_user_func_array(array(&$stmt, 'bind_param'), getRefValues($bindParamArgs));
}

$stmt->execute();

function mysqliContentType($value)
{
    if(is_string($value)) $type = 's';
    elseif(is_float($value)) $type = 'd';
    elseif(is_int($value)) $type = 'i';
    elseif($value == null) $type = 's'; //for nulls, just have to assume a string. hopefully this doesn't mess anything up.
    else throw new Exception("type of '".$value."' is not string, int or float");
    return $type;
}

function getRefValues($arr)
{
  $refs = array();

  foreach($arr as $key => $value)
  {
    $refs[$key] = &$arr[$key];
  }

  return $refs;
}
Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...