Doc #62914 [Com]: First entry appears twice, unless rewind method is called first
| From: | duke at ejoom dot com | Date: | Wed, 20 Nov 2013 11:44:38 +0000 |
| Subject: | Doc #62914 [Com]: First entry appears twice, unless rewind method is called first | ||
| References: | 1 | Groups: | php.doc.bugs |
| Request: | Send a blank email to doc-bugs+get-10620@lists.php.net to get a copy of this message | ||
Edit report at https://bugs.php.net/bug.php?id=62914&edit=1
ID: 62914
Comment by: duke at ejoom dot com
Reported by: lveyde at gmail dot com
Summary: First entry appears twice, unless rewind method is
called first
Status: Assigned
Type: Documentation Problem
Package: SPL related
Operating System: CentOS 6.3
PHP Version: 5.3.16
Assigned To: salathe
Block user comment: N
Private report: N
New Comment:
Small script to reproduce bug:
<?php
$arr = array('first', 'second' => array('subsecond'));
$it = new \RecursiveIteratorIterator(new \RecursiveArrayIterator($arr));
var_dump($it->current());
$it->next();
var_dump($it->current());
$it->rewind();
var_dump($it->current());
$it->next();
var_dump($it->current());
?>
results:
string 'first' (length=5)
string 'first' (length=5)
string 'first' (length=5)
string 'subsecond' (length=9)
expects:
string 'first' (length=5)
string 'subsecond' (length=9)
string 'first' (length=5)
string 'subsecond' (length=9)
PHP 5.5.5, Ubuntu.
Previous Comments:
------------------------------------------------------------------------
[2012-09-13 05:14:12] googleguy@php.net
You stated you're using PHP version 5.3.3 in your bug description, but your bug
report says 5.3.16. I can not reproduce this behavior in PHP 5.3.16, however I have
found that it is evident in early version of 5.3, prior to 5.3.10.
Steps to reproduce:
1) Create a temporary directory somewhere and your file system and create some
empty files in that directory for testing.
cd /tmp
mkdir test
touch test1 & touch test2 & touch test3
2) Run the following PHP script
<?php
$directory = "/tmp/test";
$it = new RecursiveIteratorIterator(new RecursiveDirectoryIterator($directory));
while ($it->valid()) { if (!$it->isDot()) var_dump($it->key()); $it->next(); }
?>
Here's the output I got in PHP 5.3.2 (order is not important here):
string(15) "/tmp/test/test3"
string(15) "/tmp/test/test3"
string(15) "/tmp/test/test1"
string(15) "/tmp/test/test2"
---------------------------------
Here's the output I got in 5.3.10 all the way to the latest 5.4
string(15) "/tmp/test/test2"
string(15) "/tmp/test/test3"
string(15) "/tmp/test/test1"
------------------------------
The only potential documentation bug here is that the changelog doesn't reflect any
changes in the behavior of RecursiveDirectoryIterator that would indicate why this
bug existed. I haven't been able to find any bug reports on the issue, but
obviously it was a problem at some point. I'll see if we need to update the
changelog about this behavior and if necessary will open a bug report for SPL.
------------------------------------------------------------------------
[2012-08-26 14:52:19] phpbugs at jessemccarthy dot net
I'm running into this too, in PHP 5.3.6 (Apache module / CLI) on Ubuntu 11.10.
Test case directory structure:
test/
a/
b.php
iterate.php
while.php
foreach.php
rewind-while.php
iterator_to_array.php
iterate.php is used in all of the other scripts:
<?php
header( "Content-Type: text/plain" );
$it = new RecursiveIteratorIterator(
new RecursiveDirectoryIterator(
__DIR__ . "/a",
FilesystemIterator::SKIP_DOTS
),
RecursiveIteratorIterator::CHILD_FIRST
);
function show_items( $items ) {
var_dump( $items );
}
$items = array();
****************************************
Expected result from all scripts:
****************************************
array(1) {
[0]=>
string(5) "b.php"
}
Content of the test scripts and actual results:
****************************************
while.php
****************************************
<?php
require_once "iterate.php";
while ( $it->valid() ) {
$items[] = $it->getFilename();
$it->next();
}
show_items( $items );
========================================
array(2) {
[0]=>
string(5) "b.php"
[1]=>
string(5) "b.php"
}
****************************************
foreach.php
****************************************
<?php
require_once "iterate.php";
foreach ( $it as $file ) {
$items[] = $file->getFilename();
}
show_items( $items );
========================================
array(1) {
[0]=>
string(5) "b.php"
}
****************************************
rewind-while.php
****************************************
<?php
require_once "iterate.php";
$it->rewind();
require_once "while.php";
========================================
array(1) {
[0]=>
string(5) "b.php"
}
****************************************
iterator_to_array.php
****************************************
<?php
require_once "iterate.php";
$items = array_map( function ( $item ) {
return $item->getFilename();
}, array_values( iterator_to_array( $it ) ) );
show_items( $items );
========================================
array(1) {
[0]=>
string(5) "b.php"
}
As you can see, iterating with while and next() produces an unexpected
duplicate value, whereas foreach, iterator_to_array(), and the
rewind()
then while suggested by the OP produce the expected result.
------------------------------------------------------------------------
[2012-08-23 22:18:04] lveyde at gmail dot com
Description:
------------
---
From manual page: http://www.php.net/recursivedirectoryiterator.construct
---
I tried to run the sample code (changing the directory), and unless the call to the rewind() method
is performed before using the iterator, the first entry appears twice in the output.
I'm using PHP version 5.3.3, the latest available with RHEL/CentOS 6.x.
<?php
$directory = '/root/isos';
$it = new RecursiveIteratorIterator(new RecursiveDirectoryIterator($directory));
// Added this
$it->rewind();
while($it->valid()) {
if (!$it->isDot()) {
echo 'SubPathName: ' . $it->getSubPathName() . "\n";
echo 'SubPath: ' . $it->getSubPath() . "\n";
echo 'Key: ' . $it->key() . "\n\n";
}
$it->next();
}
?>
Is that a normal behavior (and thus bug in the documentation) ?
Test script:
---------------
<?php
$directory = '/root/isos';
$it = new RecursiveIteratorIterator(new RecursiveDirectoryIterator($directory));
while($it->valid()) {
if (!$it->isDot()) {
echo 'SubPathName: ' . $it->getSubPathName() . "\n";
echo 'SubPath: ' . $it->getSubPath() . "\n";
echo 'Key: ' . $it->key() . "\n\n";
}
$it->next();
}
?>
Expected result:
----------------
SubPathName: CentOS-6.2-x86_64-netinstall.iso
SubPath:
Key: /root/isos/CentOS-6.2-x86_64-netinstall.iso
SubPathName: CentOS-6.2-x86_64-bin-DVD1.iso
SubPath:
Key: /root/isos/CentOS-6.2-x86_64-bin-DVD1.iso
SubPathName: CentOS-6.2-x86_64-LiveCD.iso
SubPath:
Key: /root/isos/CentOS-6.2-x86_64-LiveCD.iso
SubPathName: CentOS-6.2-x86_64-bin-DVD2.iso
SubPath:
Key: /root/isos/CentOS-6.2-x86_64-bin-DVD2.iso
Actual result:
--------------
SubPathName: CentOS-6.2-x86_64-netinstall.iso
SubPath:
Key: /root/isos/CentOS-6.2-x86_64-netinstall.iso
SubPathName: CentOS-6.2-x86_64-netinstall.iso
SubPath:
Key: /root/isos/CentOS-6.2-x86_64-netinstall.iso
SubPathName: CentOS-6.2-x86_64-bin-DVD1.iso
SubPath:
Key: /root/isos/CentOS-6.2-x86_64-bin-DVD1.iso
SubPathName: CentOS-6.2-x86_64-LiveCD.iso
SubPath:
Key: /root/isos/CentOS-6.2-x86_64-LiveCD.iso
SubPathName: CentOS-6.2-x86_64-bin-DVD2.iso
SubPath:
Key: /root/isos/CentOS-6.2-x86_64-bin-DVD2.iso
------------------------------------------------------------------------
--
Edit this bug report at https://bugs.php.net/bug.php?id=62914&edit=1