|
php.net | support | documentation | report a bug | advanced search | search howto | statistics | random bug | login |
[2012-08-23 22:18 UTC] 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 PatchesPull RequestsHistoryAllCommentsChangesGit/SVN commits
|
|||||||||||||||||||||||||||||||||||||
Copyright © 2001-2025 The PHP GroupAll rights reserved. |
Last updated: Fri Nov 07 21:00:01 2025 UTC |
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.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.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.