Bug #74142 [Opn->Nab]: FilterIterator::accept called even though LimitIterator stops loop

From: Date: Tue, 21 Feb 2017 18:45:21 +0000
Subject: Bug #74142 [Opn->Nab]: FilterIterator::accept called even though LimitIterator stops loop
References: 1  Groups: php.bugs 
Request: Send a blank email to php-bugs+get-207497@lists.php.net to get a copy of this message
Edit report at https://bugs.php.net/bug.php?id=74142&edit=1 ID: 74142 Updated by: requinix@php.net Reported by: nicolas dot levee at gmail dot com -Summary: LimitIterator > FilterIterator issue +Summary: FilterIterator::accept called even though LimitIterator stops loop -Status: Open +Status: Not a bug Type: Bug Package: SPL related Operating System: Linux PHP Version: 7.0.16 Block user comment: N Private report: N New Comment: 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. Previous Comments: ------------------------------------------------------------------------ [2017-02-21 17:39:44] 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 ------------------------------------------------------------------------ -- Edit this bug report at https://bugs.php.net/bug.php?id=74142&edit=1

« previous php.bugs (#207497) next »