PHP + MYSQLI: привязка переменной / результата к подготовленным операторам

В проекте, который я собираюсь завершить, я написал и реализовал решение объектно-реляционного отображения для PHP. Прежде чем сомневающиеся и мечтатели закричат ​​«как на земле?», Расслабьтесь - я не нашел способа заставить позднюю статическую привязку работать - я просто работаю над этим наилучшим способом, каким только могу.

Во всяком случае, в настоящее время я не использую подготовленные операторы для запросов, потому что я не смог придумать способ передать переменное число аргументов в методы bind_params()или bind_result().

Вы спрашиваете, почему мне нужно поддерживать переменное количество аргументов? Потому что суперкласс моих моделей (представьте, что мое решение - взломанный PHP ActiveRecord wannabe) - это то место, где определены запросы, и поэтому метод find (), например, не знает, сколько параметров ему нужно связать ,

Я уже думал о создании списка аргументов и передаче строки в eval (), но мне это решение не очень нравится - я бы предпочел просто реализовать свои собственные проверки безопасности и передать операторы.

У кого-нибудь есть предложения (или истории успеха) о том, как это сделать? Если вы можете помочь мне решить эту первую проблему, возможно, мы сможем решить проблему связывания набора результатов (что, я подозреваю, будет более сложным или, по крайней мере, более ресурсоемким, если для определения структуры таблицы потребуется начальный запрос).

15.08.2008 19:50:52
5 ОТВЕТОВ
РЕШЕНИЕ

В PHP вы можете передать переменное число аргументов функции или методу с помощью call_user_func_array. Примером метода будет:

call_user_func_array(array(&$stmt, 'bindparams'), $array_of_params);

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

13
16.08.2008 11:36:21
Я думаю, что имя функции должно быть bind_paramвместо bindparams. По крайней мере, с моей mysqliверсией я использую его $stmt->bind_param(), а не $stmt->bindparams(). Ура!
Dani Sancas 3.01.2014 11:33:00

Мне не разрешено редактировать, но я верю в код

call_user_func_array(array(&$stmt, 'bindparams'), $array_of_params);

Ссылка перед $ stmt необязательна. Поскольку $stmtэто объект и bindparamsметод в этом объекте, ссылка не обязательна. Так должно быть:

call_user_func_array(array($stmt, 'bindparams'), $array_of_params);

Для получения дополнительной информации см. Руководство PHP по функциям обратного вызова . "

1
17.11.2008 06:33:57
call_user_func_array(array(&$stmt, 'bindparams'), $array_of_params);

Не работал для меня в моем окружении, но этот ответ поставил меня на правильный путь. Что на самом деле работало:

$sitesql = '';
$array_of_params = array();
foreach($_POST['multiselect'] as $value){
    if($sitesql!=''){
        $sitesql .= "OR siteID=? ";
        $array_of_params[0] .= 'i';
        $array_of_params[] = $value;
    }else{
        $sitesql = " siteID=? ";
        $array_of_params[0] .= 'i';
        $array_of_params[] = $value;
    }
}

$stmt = $linki->prepare("SELECT IFNULL(SUM(hours),0) FROM table WHERE ".$sitesql." AND week!='0000-00-00'");
call_user_func_array(array(&$stmt, 'bind_param'), $array_of_params);
$stmt->execute();
1
4.04.2010 20:11:05

Вы должны убедиться, что $ array_of_params - это массив ссылок на переменные , а не сами значения. Должно быть:

$array_of_params[0] = &$param_string; //link to variable that stores types

А потом...

$param_string .= "i";
$user_id_var = $_GET['user_id'];//
$array_of_params[] = &$user_id_var; //link to variable that stores value

В противном случае (если это массив значений) вы получите:

Предупреждение PHP: параметр 2 для mysqli_stmt :: bind_param () должен быть ссылкой


Еще один пример:

$bind_names[] = implode($types); //putting types of parameters in a string
for ($i = 0; $i < count($params); $i++)
{
   $bind_name = 'bind'.$i; //generate a name for variable bind1, bind2, bind3...
   $$bind_name = $params[$i]; //create a variable with this name and put value in it
   $bind_names[] = & $$bind_name; //put a link to this variable in array
}

и BOOOOOM:

call_user_func_array( array ($stmt, 'bind_param'), $bind_names); 
2
30.08.2011 09:03:23

Более современный способ динамического связывания параметров - через оператор splat / spread ( ...).

Предполагая, что:

  • у вас есть непустой массив значений для привязки к вашему запросу и
  • Ваши значения массива соответствующим образом обрабатываются как значения строкового типа в контексте запроса и
  • Ваш входной массив называется $values

Код для PHP5.6 и выше:

$stmt->bind_param(str_repeat('s', count($values)), ...$values); 
0
13.10.2019 13:51:01