Клонирование объекта набора записей PHP PDO для подсчета строк, возвращаемых оператором select

#php #sqlite #pdo

#php #sqlite #pdo

Вопрос:

Я рефакторингую часть PHP-приложения, которое использует adodb в качестве библиотеки db, чтобы начать использовать PDO.

Мне нужно что-то, что предоставляет мне количество строк, включенных в выбранный набор записей, что-то, что может легко заменить старый $rs->RecordCount() метод adodb, который я использовал ранее. Это должно работать для sqlite3.

Я не могу просто повторно выполнить запрос (или повторно выполнить запрос с помощью select count(*) ), потому что я не могу так сильно изменить исходное приложение, приложение вызывает во многих частях функцию get_num_rows($rs) (которая содержит только $rs->RecordCount() ), и я могу просто изменить содержимое этой функции.

Я попробовал клонировать объект набора записей и подсчитать извлеченные записи:

 function get_num_rows($rs)
{
    $rs_copy = clone $rs;
    return (count($rs_copy->fetchAll()));
}
  

но это не работает, потому что $rs_copy->fetchAll() возвращает меня false . Я не могу сделать это для исходного набора записей, потому что позже в приложении мне нужно будет извлечь его снова, и я думаю, что в PDO sqlite нет способа повторно использовать набор записей (поправьте меня, если я ошибаюсь).

Есть ли у вас какие-либо решения?

Комментарии:

1. Что вы пытаетесь получить? Количество всех строк для реализации разбивки на страницы или количество возвращенных строк?

2. @nikic: $result -> rowCount () работает только для обновлений.

3. Пожалуйста, попробуйте это для клонирования $rs_copy = несериализовать(serialize($ rs));

4. @Gaurav: Объекты PDO не могут быть сериализованы.

5. Вам не нужно ни подсчитывать количество строк, ни выполнять другую выборку позже в приложении . Просто сразу извлеките его в массив, а затем используйте функцию count(). Если вы не можете изменить окружающий код, вам лучше оставить текущий ADODB в покое

Ответ №1:

Использование SELECT COUNT(*) FROM run в качестве второго запроса — рекомендуемый способ подсчета количества строк в результирующем наборе при использовании LIMIT в вашем основном запросе. Он не будет извлекать одни и те же данные дважды, он просто подсчитывает, сколько найдено строк, и возвращает 1 строку, целое число. Другой способ определить количество строк при использовании LIMIT инструкции — использовать SELECT SQL_CALC_FOUND_ROWS (field list) FROM ... в вашем первом запросе, затем выполнить SELECT FOUND_ROWS() , чтобы получить количество строк, однако этот метод работает медленнее, чем предыдущий упомянутый. Имейте в виду, что запуск count() на PHP выдаст вам только количество возвращенных строк, а не фактическое количество строк, найденных в базе данных (если вы используете LIMIT ).

Приветствия

Ответ №2:

Возможно, есть возможность поступить так, как предложил col shrapnel, и сохранить результат в массиве. Возможно, вам удастся сохранить интерфейс чистым, расширив PDOStatement, а затем

http://www.php.net/manual/en/pdo.setattribute.php PDO::ATTR_STATEMENT_CLASS

Таким образом, он вернет вам EugenioEnhancedPDOStatement

Ответ №3:

Спасибо всем. Я нашел более простое, быстрое и грязное решение, мое новое get_num_rows() будет чем-то вроде:

 $temp_ar = explode("FROM", $rs->queryString);

$sql = "SELECT COUNT(*) FROM ".$temp_ar[1];

$conn->query($sql);

...
  

Комментарии:

1. используйте третий аргумент для explode(), чтобы он разделялся только один раз.

Ответ №4:

Вы не можете должным образом клонировать и / или сериализовать / несериализовать объекты PDO, скорее всего, потому, что они тесно привязаны к ресурсу подключения.

Дело в том, что клонировать его нет смысла. Если $rs это объект PDOStatement, вы можете просто повторно выполнить его, поскольку у вас есть к нему доступ. Это одно из основных преимуществ подготовленных инструкций, подготавливается один раз, выполняется несколько раз.

Вот так:

 function get_num_rows($rs)
{
 $rs->execute();
 return (count($rs->fetchAll()));
}
  

Вы догадались: вызов execute() в том же экземпляре PDOStatement во второй раз без указания каких-либо параметров приведет к повторному использованию последнего набора параметров и повторному выполнению инструкции как есть.

Следовательно, нет необходимости клонировать объекты PDOStatement.

Комментарии:

1. Эта извращенная задача (дважды извлекать одни и те же данные только для того, чтобы их посчитать), конечно, не для того, для чего был изобретен PDO.

2. @Col. Shrapnel: Я согласен, что это не так, и я никогда не говорил, что это так. Я отвечаю на вопрос OP. Конечно, это не оптимально: но я не собираюсь переписывать весь его код за него. Если у вас есть лучшее наглядное решение этой проблемы, я хотел бы увидеть его в ответе. Возможно, я даже проголосую за это. 🙂

3. Я так и не нашел решения проблемы, в которой не вижу смысла

4. Я не понимаю, почему вы не видите в этом смысла, мне просто нужно получить количество строк в функции, не касаясь всего остального кода.