Привязка переменных параметров / результатов с подготовленными операторами

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

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

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

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

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

Стоит ли изучать PHP в 2026-2027 годах?
Стоит ли изучать PHP в 2026-2027 годах?
Привет всем, сегодня я хочу высказать свои соображения по поводу вопроса, который я уже много раз получал в своем сообществе: "Стоит ли изучать PHP в...
Symfony Station Communiqué - 7 июля 2023 г
Symfony Station Communiqué - 7 июля 2023 г
Это коммюнике первоначально появилось на Symfony Station .
Оживление вашего приложения Laravel: Понимание режима обслуживания
Оживление вашего приложения Laravel: Понимание режима обслуживания
Здравствуйте, разработчики! В сегодняшней статье мы рассмотрим важный аспект управления приложениями, который часто упускается из виду в суете...
Установка и настройка Nginx и PHP на Ubuntu-сервере
Установка и настройка Nginx и PHP на Ubuntu-сервере
В этот раз я сделаю руководство по установке и настройке nginx и php на Ubuntu OS.
Коллекции в Laravel более простым способом
Коллекции в Laravel более простым способом
Привет, читатели, сегодня мы узнаем о коллекциях. В Laravel коллекции - это способ манипулировать массивами и играть с массивами данных. Благодаря...
Как установить PHP на Mac
Как установить PHP на Mac
PHP - это популярный язык программирования, который используется для разработки веб-приложений. Если вы используете Mac и хотите разрабатывать...
9
0
5 199
5
Перейти к ответу Данный вопрос помечен как решенный

Ответы 5

Ответ принят как подходящий

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

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

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

Я думаю, что имя функции должно быть bind_param, а не bindparams. По крайней мере, в моей версии mysqli я набираю $stmt->bind_param(), а не $stmt->bindparams(). Ваше здоровье!

Dani Sancas 03.01.2014 15:33

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

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();

Вы должны убедиться, что $ 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 Warning: Parameter 2 to mysqli_stmt::bind_param() expected to be a reference


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

$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
}

и БУУУМ:

call_user_func_array( array ($stmt, 'bind_param'), $bind_names); 

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

Предполагая:

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

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

$stmt->bind_param(str_repeat('s', count($values)), ...$values);

Фактически, все аргументы, передаваемые в bind_param(), могут быть распакованы с помощью оператора splat / spread, если хотите - строка типов данных просто должна быть первым элементом массива.

array_unshift($values, str_repeat('s', count($values)));
$stmt->bind_param(...$values);

Другие вопросы по теме