Рекурсия в подготовленных операторах

Я использовал 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 будет использовать подготовленный оператор так или иначе, таким образом, будут только маленькие издержки создания нового дескриптора на каждом рекурсивном вызове. Лично я думаю, что побеждает точку.

Или есть ли некоторый способ переписать это?

8
задан Rob 26 April 2010 в 14:31
поделиться

2 ответа

Вы не можете вложить дескрипторы операторов: вам нужно закрыть ранее открытый дескриптор, прежде чем открывать другой в пределах разовая сессия.

Фактически, PDO делает это автоматически, когда вы запускаете новую подготовку.

Когда вы вызываете функцию рекурсивно:

  • Первоначальный дескриптор выделяется (1)
  • Первая запись извлекается из (1)
  • Функция вызывается рекурсивно. Значение (1) находится в стеке рекурсии.
  • Новый дескриптор выделяется (2) , делает недействительным (1)
  • Первая запись извлекается из (2)
  • Функция возвращает
  • Вы пытаетесь получить следующую запись (1) и терпите неудачу, поскольку она недействительна

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

3
ответ дан 6 December 2019 в 00:54
поделиться

Настоящая проблема в том, что $ handle статичен. Статические переменные проблематичны для рекурсии, когда состояние необходимо сохранить при рекурсивном вызове, а не только для подготовленных операторов. В этом случае рекурсивный вызов выполняет новый запрос, отбрасывая предыдущее состояние. PDO :: fetchAll действительно единственный вариант, если вам нужен единственный подготовленный запрос.

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

0
ответ дан 6 December 2019 в 00:54
поделиться
Другие вопросы по тегам:

Похожие вопросы: