Привязать параметры к частичной инструкции SQL

Я имею дело со старым приложением PHP, и мне было поручено убедиться, что во всех областях используются подготовленные операторы. В настоящее время он использует sprintf для построения большей части запроса перед выполнением.

Ниже приведен пример кода текущей реализации:

$queryString = "SELECT count(user.uid) as count
FROM user
LEFT JOIN voucher
ON user.voucher_uid = voucher.uid
LEFT JOIN affiliation
ON voucher.uid = affiliation.voucher_uid
@affiliation
LEFT JOIN account
ON affiliation.account_uid = account.uid
WHERE affiliation.account_uid IN (@accounts)
@active
@search
@template
@onlyown
AND voucher.template NOT LIKE 'api_%'
AND user.role != 'superadmin'";
$sql = replace_tokens(
$queryString,
array(
'accounts' => implode(', ', array_fill(0, count($accounts), '?')),
'template' => $template,
'search' => $search,
'onlyown' => $onlyown,
'affiliation' => $affiliation,
'active' => $active
)
);

return array_get(self::queryFetchOne($sql, $accounts), 'count', 0);

replace_tokens Функция заменяет переменные, объявленные с @, перед ними на sql. Вот пример того, как @search Переменная построена.

if (is_string($search) && !empty($search)) {
$search = sprintf('AND (voucher.code LIKE "%%%s%%" OR user.email LIKE "%%%s%%" OR user.salutation LIKE "%%%s%%")', $search, $search, $search);
} else {
$search = '';
}

Теперь я хотел бы решить проблему поиска, изменив %%%s%% в :search и просто используя именованный параметр. Тем не менее $accounts Переменная является массивом имен учетных записей и использует параметры вопросительного знака для оператора in.

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

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

1

Решение

Я решаю эту проблему путем создания двух переменных: одна — строка запроса, а другая — хеш-массив параметров запроса.

if (is_string($search) && !empty($search)) {
$search = 'AND (voucher.code LIKE :code OR user.email LIKE :email OR user.salutation LIKE :salutation)';
$params['code'] = "%%$search%%";
$params['email'] = "%%$search%%";
$params['salutation'] = "%%$search%%";
} else {
$search = '';
}

К тому времени, как вы закончите со всем условным кодом, у вас будет хэш-массив параметров запроса, который вы можете передать в PDO execute(),

Но вы должны убедиться, что все ваши именованные параметры являются уникальными. Если вы используете одни и те же имена в разных условных терминах поиска, наступит хаос. В этом случае позиционные параметры имеют преимущество.

0

Другие решения

Это ошибка инженерии.

Моя рекомендация; массив с переменными, который соответствует параметрам.
Например

Позволять $sql1 = "select * from Apples where a=? and b=?"

А также $sql2 = " or c=?;"

Оба сгенерированы из функций gen_sql1() а также gen_sql2(),

Просто иметь gen_sql1 вернуть первую половину массива: 1, 2, Есть gen_sql2 Верните второй тайм: 3,

В конце объедините массивы и получите массив и вставьте их в «?» параметры в соответствующем порядке:

$fullsql = "select * from Apples where a=1 and b=2 or c=3"

0

По вопросам рекламы ammmcru@yandex.ru
Adblock
detector