PHP 的 PDO 循环返回除第一行之外的所有内容

发布于 2024-10-21 17:36:54 字数 638 浏览 3 评论 0原文

symfony (v1.4.6) 下,PDOStatement->fetch 出现问题,因为从语句第一行获取记录始终被排除。

下面的代码:

<?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

有什么想法为什么行被排除吗?

Got problem with PDOStatement->fetch under symfony (v1.4.6) as while fetching records from statement first row is always excluded.

Code bellow:

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

Produces:

int 14
int 13

And code bellow:

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

Produces:

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

Any ideas why row is excluded?

如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。

扫码二维码加入Web技术交流群

发布评论

需要 登录 才能够评论, 你可以免费 注册 一个本站的账号。

评论(4

过潦 2024-10-28 17:36:54

引用PDOStatement->rowCount

如果最后执行的 SQL 语句是
相关的 PDOStatement 是
SELECT 语句,某些数据库可能
返回返回的行数
那个声明。
但是,这个
无法保证所有人的行为

不应依赖数据库和
对于便携式应用程序,请打开

以及示例#2 的注释:

对于大多数数据库,
PDOStatement::rowCount()
返回受影响的行数
SELECT 语句。
相反,
使用 PDO::query() 发出具有相同内容的 SELECT COUNT(*) 语句
谓词作为您想要的 SELECT
声明,然后使用
PDOStatement::fetchColumn()
检索将要执行的行数
被退回。
您的应用程序可以
然后执行正确的操作。

因此,这并不是对您问题的原因的真正答案,但我想说您不应该使用 rowCount() 进行 select 查询; -)

See also the notes on that documentation page ; for example, [this one][2], which says *(quoting)* :

看来 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

Quoting the documentation of PDOStatement->rowCount :

If the last SQL statement executed by
the associated PDOStatement was a
SELECT statement, some databases may
return the number of rows returned by
that statement.
However, this
behaviour
is not guaranteed for all
databases and should not be relied
on
for portable applications.

and the note on Example #2 :

For most databases,
PDOStatement::rowCount() does not
return the number of rows affected by
a SELECT statement.
Instead,
use PDO::query() to issue a SELECT COUNT(*) statement with the same
predicates as your intended SELECT
statement, then use
PDOStatement::fetchColumn() to
retrieve the number of rows that will
be returned.
Your application can
then perform the correct action.

So, not really an answer to the why of your question, but I would say you should not use rowCount() for a select query ;-)

See also the notes on that documentation page ; for example, [this one][2], which says *(quoting)* :

It appears that rowCount behavior is
different on Mysql 5.0 vs 5.1.

And, with a query as simple as "SELECT 1" :

Mysql 5.0.45, PHP 5.2.5 returned 1

Mysql 5.1.30, PHP 5.1.6 returned 0

还如梦归 2024-10-28 17:36:54

问题已解决,它与 PDO 无关,而是与 Symfony 相关的问题(我认为是 OutputDecorators 之一,但还不确定)

PDOStatement 是有效的,并且在使用 -> 循环它时,它是有效的。在控制器内 fetch 一切都很好(检索到 14 条记录)。移动相同的代码来查看第一条记录后,总是从结果中排除(我认为它与使用 Iterator 和 ArrayAccess 的输出装饰器有关)。

此问题的快速解决方法不是使用 while 循环,而是使用实现的 Iterator 和 ArrayAccess ,以便最终代码按预期工作(返回所有行) ) 使用 foreach

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

代替 while + ->fetch() 循环

<?php while ($v = $stats->fetch()): ?>
    <?php //1st record is missing here somehow ?>
<?php endwhile; ?>

Problem SOLVED and it wasn't PDO related but Symfony related problem (one of the OutputDecorators i think but don't know sure yet)

PDOStatement was valid and when looping through it with ->fetch inside controller everything was fine (14 records retrieved). After moving the same code to view first record was always excluded from results (and i think its related with that output decorators are using Iterator and ArrayAccess).

Quick workaround for this issue is NOT using while loop but make usage of implemented Iterator and ArrayAccess so final code that works as expected (returns all rows) is using foreach

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

insted of while + ->fetch() loop

<?php while ($v = $stats->fetch()): ?>
    <?php //1st record is missing here somehow ?>
<?php endwhile; ?>
ぇ气 2024-10-28 17:36:54

我也遇到了同样的问题,解决此问题的一种方法是 fetchAll() 并迭代数组。就我而言,这导致了第二个问题:迭代超过 10,000 条记录会出现内存错误。

在深入研究 Symfony 之后,我发现可以直接设置变量(在操作方法中使用 $this->setVar)。 setVar 有 3 个参数:视图中的变量名称、实际数据以及数据是否安全(将被转义)。当数据不安全/转义时,所有记录都在mysql语句中。允许您使用 fetch 循环遍历行。

I also had the same problem, one way to solve this is to fetchAll() and iterate over the array. In my case this caused a second problem: iterating over 10.000 records gave a memory error.

After some digging in to Symfony I saw there is a posibility to set variables directly instead (using $this->setVar in your action methods). setVar has 3 parameters: the variable name in the view, the actual data, and if the data is safe (than it will be escaped). When the data isn't safe / escaped, all records are in the mysql statement. Allowing you to loop over row with fetch.

梦中楼上月下 2024-10-28 17:36:54

我刚刚遇到了同样的问题(迭代行时第一行没有显示),但这是我自己的错。

在我的模板中,我有:

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

当 PDOStatement 有任何行时,foreach 循环将始终排除第一行。

显然(我现在意识到),if 语句正在调用 fetch(),这会将光标向前移动一位。所以,if 语句吃掉了第一行!德普。

I just ran into this same problem (first row not showing up while iterating over rows), but it was my own fault.

In my template I had:

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

When the PDOStatement had any rows the foreach loop would always exclude the first row.

Obviously (I realize now), the if-statement is calling fetch(), which will move the cursor forward by one. So, the if-statement was eating up the first row! Derp.

~没有更多了~
我们使用 Cookies 和其他技术来定制您的体验包括您的登录状态等。通过阅读我们的 隐私政策 了解更多相关信息。 单击 接受 或继续使用网站,即表示您同意使用 Cookies 和您的相关数据。
原文