PHP + MYSQLI: Привязка переменных параметров/результатов с подготовленными инструкциями
В проекте, который я собираюсь завершить, я написал и реализовал решение объектно-реляционного отображения для PHP. Прежде чем сомневающиеся и мечтатели воскликнут "как же так?", расслабьтесь - я не нашел способа заставить работать позднюю статическую привязку - я просто работаю над этим наилучшим образом, насколько это возможно.
В любом случае, в настоящее время я не использую подготовленные операторы для запросов, потому что я не смог придумать способ передачи переменного числа аргументов в bind_params()
или bind_result()
методы.
Почему мне нужно поддерживать переменное количество аргументов, спросите вы? Потому что суперкласс моих моделей (думайте о моем решении как о взломанном подражателе PHP ActiveRecord) - это то, где определен запрос, и поэтому метод find(), например, не знает, сколько параметров ему нужно будет связать.
Теперь я уже думал о создании списка аргументов и передаче строки в eval(), но мне не очень нравится это решение - я бы предпочел просто реализовать свою собственную безопасность проверяет и передает выписки.
Есть ли у кого-нибудь какие-либо предложения (или истории успеха) о том, как это сделать? Если вы поможете мне решить эту первую проблему, возможно, мы сможем заняться привязкой результирующего набора (что, как я подозреваю, будет сложнее или, по крайней мере, более ресурсоемким, если это потребует первоначального запроса для определения структуры таблицы).
4 answers
В PHP вы можете передать переменное количество аргументов функции или методу с помощью call_user_func_array
. Примером метода может быть:
call_user_func_array(array(&$stmt, 'bindparams'), $array_of_params);
Функция будет вызываться с каждым членом массива, переданным в качестве собственного аргумента.
Вы должны убедиться, что $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);
Мне не разрешено редактировать, но я верю в код
call_user_func_array(array(&$stmt, 'bindparams'), $array_of_params);
Ссылка перед $stmt не требуется. Поскольку $stmt
является объектом, а bindparams
- методом в этом объекте, ссылка не требуется. Это должно быть:
call_user_func_array(array($stmt, 'bindparams'), $array_of_params);
Для получения дополнительной информации см. Руководство PHP по функциям обратного вызова ."
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();