В проекте, который я собираюсь завершить, я написал и внедрил решение для объектно-реляционного сопоставления для PHP. Перед тем, как сомневающиеся и мечтатели кричат «как на земле?», Расслабьтесь – я не нашел способ сделать позднюю статическую работу по связыванию – я просто оборачиваю ее наилучшим образом, как я могу.
Во всяком случае, я в настоящее время не использую подготовленные инструкции для запросов, потому что я не мог придумать способ передать переменное количество аргументов bind_params()
или bind_result()
.
Почему мне нужно поддерживать переменное количество аргументов, спросите вы? Поскольку суперкласс моих моделей (думаю, мое решение как взломанный PHP ActiveRecord wannabe) – это то, где определяется запрос, поэтому метод find (), например, не знает, сколько параметров ему потребуется связать ,
Теперь я уже думал о создании списка аргументов и передаче строки в eval (), но мне не очень нравится это решение – я бы предпочел просто реализовать свои собственные проверки безопасности и передать инструкции.
У кого-нибудь есть предложения (или истории успеха) о том, как это сделать? Если вы можете помочь мне решить эту первую проблему, возможно, мы сможем связать результирующий набор (то, что я подозреваю, будет более сложным или, по крайней мере, более ресурсоемким, если оно включает в себя начальный запрос для определения структуры таблицы).
В 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();