Я использовал PDO и готовил все мои операторы, прежде всего, к соображениям безопасности. Однако у меня есть часть моего кода, который действительно много раз выполняет тот же оператор с различными параметрами, и я думал, что это будет то, где подготовленные операторы действительно сияют. Но они на самом деле взламывают код...
Основная логика кода - это.
function someFunction($something) {
global $pdo;
$array = array();
static $handle = null;
if (!$handle) {
$handle = $pdo->prepare("A STATEMENT WITH :a_param");
}
$handle->bindValue(":a_param", $something);
if ($handle->execute()) {
while ($row = $handle->fetch()) {
$array[] = someFunction($row['blah']);
}
}
return $array;
}
Это выглядело хорошо мне, но это пропускало много строк. В конечном счете я понял, что дескриптор оператора изменялся (выполняемый с другим параметрическим усилителем), что означает, что вызов для выборки в цикле с условием продолжения будет только когда-либо работать однажды, затем вызовы функции самом снова, и набор результатов изменяется.
Таким образом, я задаюсь вопросом, каков лучший способ использовать подготовленные операторы PDO рекурсивным способом.
Один путь мог состоять в том, чтобы использовать fetchAll (), но он говорит в руководстве, которое имеет существенные издержки. Смысл этого должен сделать это более эффективным.
Другой вещью, которую я мог сделать, не является повторное использование статический дескриптор, и вместо этого сделайте новый каждым разом. Я полагаю, что, так как строка запроса является тем же, внутренне драйвер MySQL будет использовать подготовленный оператор так или иначе, таким образом, будут только маленькие издержки создания нового дескриптора на каждом рекурсивном вызове. Лично я думаю, что побеждает точку.
Или есть ли некоторый способ переписать это?
Вы не можете вложить дескрипторы операторов: вам нужно закрыть ранее открытый дескриптор, прежде чем открывать другой в пределах разовая сессия.
Фактически, PDO
делает это автоматически, когда вы запускаете новую подготовку.
Когда вы вызываете функцию рекурсивно:
(1)
(1)
(1)
находится в стеке рекурсии. (2)
, делает недействительным (1)
(2)
(1)
и терпите неудачу, поскольку она недействительна Таким образом, MySQL
не поддерживает рекурсию на своей стороне, и это означает, что вы это необходимо сделать на стороне PHP
, используя fetchAll
.
Настоящая проблема в том, что $ handle
статичен. Статические переменные проблематичны для рекурсии, когда состояние необходимо сохранить при рекурсивном вызове, а не только для подготовленных операторов. В этом случае рекурсивный вызов выполняет новый запрос, отбрасывая предыдущее состояние. PDO :: fetchAll
действительно единственный вариант, если вам нужен единственный подготовленный запрос.
В зависимости от того, что это за оператор, вы потенциально можете переписать его, чтобы возвращать все результаты сразу, а после этого построить дерево.