php.net |  support |  documentation |  report a bug |  advanced search |  search howto |  statistics |  random bug |  login
Bug #74142 FilterIterator::accept called even though LimitIterator stops loop
Submitted: 2017-02-21 17:39 UTC Modified: 2017-02-21 18:45 UTC
Votes:1
Avg. Score:3.0 ± 0.0
Reproduced:0 of 1 (0.0%)
From: nicolas dot levee at gmail dot com Assigned:
Status: Not a bug Package: SPL related
PHP Version: 7.0.16 OS: Linux
Private report: No CVE-ID: None
Welcome back! If you're the original bug submitter, here's where you can edit the bug or add additional notes.
If you forgot your password, you can retrieve your password here.
Password:
Status:
Package:
Bug Type:
Summary:
From: nicolas dot levee at gmail dot com
New email:
PHP Version: OS:

 

 [2017-02-21 17:39 UTC] nicolas dot levee at gmail dot com
Description:
------------
When a LimitIterator is use after a FilterIterator (or CallbackFilterIterator) the  accept function is call after the limit but if we invert the 2 iterator it's ok.

Test script:
---------------
class TestFilterIterator extends FilterIterator
{
    public function accept()
    {
        echo  __FUNCTION__, PHP_EOL;
        return true;
    }
}

$iterator = new ArrayIterator(array('a', 'b', 'c', 'd'));
$iterator = new TestFilterIterator($iterator);
$iterator = new LimitIterator($iterator, 0, 2);
foreach ($iterator as $k => $v) {
    echo PHP_EOL;
}

Expected result:
----------------
accept

accept



Actual result:
--------------
accept

accept

accept


Patches

Pull Requests

History

AllCommentsChangesGit/SVN commitsRelated reports
 [2017-02-21 18:45 UTC] requinix@php.net
-Summary: LimitIterator > FilterIterator issue +Summary: FilterIterator::accept called even though LimitIterator stops loop -Status: Open +Status: Not a bug
 [2017-02-21 18:45 UTC] requinix@php.net
This is expected behavior due to how iterators work. Take a look at
  http://php.net/manual/en/class.iterator.php
for more information about how the various methods are called by PHP.

To show the complex interaction between the three iterators it helps to add a couple items that the filter will reject...

What methods are being called in what order: https://3v4l.org/U61Ii
Annotated: https://gist.github.com/requinix/586a974f24a3ff8f3296f193bb871956

The key is that next() is invoked during iteration before valid(), and it's during the next() call that FilterIterator uses accept() - because it needs to advance to the next acceptable value. After this call is valid() and that's when LimitIterator's limit kicks in and can stop the loop; FilterIterator does not know that LimitIterator will not use the value it had advanced to.
 
PHP Copyright © 2001-2025 The PHP Group
All rights reserved.
Last updated: Sun Jul 13 14:01:31 2025 UTC