Использование параметризованных запросов в MySQL позволяет практически исключить возможность взлома вашего сайта при помощи SQL-инъекции. Не нужно вспоминать про экранирование кавычек и прочие прелести подстановки переменных в запрос, знай себе подавай параметры в функцию bind_params.
Однако периодически возникает небольшая проблема: что делать, если запрос строится динамически, и число параметров заранее неизвестно.
Проблему можно решить с помощью функции call_user_func_array. В качестве притянутого за уши примера возьмём выборку людей по фамилии, имени или отчеству.
function load_people_list($mysql, $firstname, $lastname, $patrname) {
$sql = 'SELECT * FROM people';
$where = array(); // Условия WHERE
$params = array(); // Аргументы функции bind_params
// Строка с типами параметров. Поскольку она идет первым аргументом в bind_params,
// в массив аргументов добавляем её тоже первой
$param_types = '';
$params[] = &$param_types;
if (strlen($firstname) > 0) {
$param_types .= 's';
// Поскольку функция bind_params требует передачи параметров по ссылке,
// в массив аргументов добавляем их также по ссылке
$params[] = &$firstname;
$where[] = 'firstname=?';
}
if (strlen($lastname) > 0) {
$param_types .= 's';
$params[] = &$lastname;
$where[] = 'lastname=?';
}
if (strlen($patrname) > 0) {
$param_types .= 's';
$params[] = &$patrname;
$where[] = 'patrname=?';
}
// Собираем запрос
if (count($where) > 0)
$sql .= ' WHERE ' . implode(' AND ', $where);
$stmt = $mysql->prepare($sql);
// Первым параметром call_user_func_array идет имя вызываемой функции.
// В данном случае вызовется $stmt->bind_param()
// Вторым параметром идет массив аргументов для вызываемой функции.
if (count($params) > 1)
call_user_func_array(array($stmt, 'bind_param'), $params);
$stmt->execute();
return $stmt;
}