Цикл PDO PHP, возвращающий все, кроме первой строки - PullRequest
4 голосов
/ 13 марта 2011

Возникла проблема с PDOStatement->fetch в symfony (v1.4.6), поскольку при извлечении записей из первой строки оператора всегда исключается.

Код ниже:

<?php var_dump($stats->rowCount()); ?>
<?php var_dump(count($stats->fetchAll())); ?>

Производит:

int 14
int 13

И код ниже:

<?php $i = 0; ?>
<?php var_dump($stats->rowCount()); ?>
<?php while ($v = $stats->fetch()): ?>
    <?php var_dump(++$i); ?>

Производит:

int 14
int 1
int 2
int 3
int 4
int 5
int 6
int 7
int 8
int 9
int 10
int 11
int 12
int 13

Есть идеи, почему исключается строка?

Ответы [ 4 ]

4 голосов
/ 13 марта 2011

Цитирование документации PDOStatement->rowCount:

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

и примечание к Примеру №2:

Для большинства баз данных PDOStatement::rowCount() не вернуть количество строк, затронутых SELECT заявление.
Вместо этого, используйте PDO::query() для выдачи оператора SELECT COUNT(*) с тем же предикаты как и предполагалось SELECT заявление, а затем использовать PDOStatement::fetchColumn() до получить количество строк, которые будут быть возвращенным.
Ваша заявка может затем выполните правильное действие.

Таким образом, на самом деле не является ответом на почему вашего вопроса, но я бы сказал, что вы не должны использовать rowCount() для select запроса; -)


Смотрите также примечания на этой странице документации; например, этот , который говорит (цитирование) :

Похоже, что поведение rowCount отличается на Mysql 5.0 против 5.1.

И с таким простым запросом, как "SELECT 1":

Mysql 5.0.45, PHP 5.2.5 вернул 1
Mysql 5.1.30, PHP 5.1.6 вернул 0

2 голосов
/ 13 марта 2011

Проблема РЕШЕНО и это не было связано с PDO, но проблема связана с Symfony (один из OutputDecorator, я думаю, но пока не знаю точно)

PDOStatement был действителен, и при циклическом прохождении с ->fetch внутри контроллера все было в порядке (получено 14 записей). После перемещения одного и того же кода для просмотра первая запись всегда исключалась из результатов (и я думаю, что это связано с тем, что выходные декораторы используют Iterator и ArrayAccess).

Быстрый обходной путь для этой проблемы - НЕ использовать while loop, а использовать реализованные Iterator и ArrayAccess, поэтому в конечном коде, который работает как ожидается (возвращает все строки), используется foreach

<?php foreach ($stats as $v): ?>
    <?php //do stuff with record ?>
<?php endforeach; ?>

insted из while + ->fetch() loop

<?php while ($v = $stats->fetch()): ?>
    <?php //1st record is missing here somehow ?>
<?php endwhile; ?>
1 голос
/ 02 января 2013

Я только что столкнулся с этой же проблемой (первая строка не отображается при переборе по строкам), но это была моя собственная ошибка.

В моем шаблоне у меня было:

<?php if(!$statement_iter->fetch()): ?>
...
<?php endif; ?>
<?php foreach($statement_iter as $row): ?>
...
<?php endforeach; ?>

Когда в PDOStatement были какие-либо строки, цикл foreach всегда исключал бы первую строку.

Очевидно (теперь я понимаю), оператор if вызывает fetch (), который переместит курсор вперед на единицу.Итак, if-оператор съел первый ряд!Derp.

1 голос
/ 10 октября 2011

У меня тоже была такая же проблема, один из способов решить эту проблему - fetchAll() и выполнить итерацию по массиву.В моем случае это вызвало вторую проблему: итерирование более 10.000 записей дало ошибку памяти.

После некоторого поиска в Symfony я увидел, что есть возможность устанавливать переменные напрямую (используя $this->setVar в ваших методах действия).).setVar имеет 3 параметра: имя переменной в представлении, фактические данные и, если данные безопасны (чем они будут экранированы).Когда данные не защищены / не защищены, все записи находятся в операторе mysql.Позволяет вам перебирать строки с помощью fetch.

...