[php-src] Issue #8156: Classes extending `SplFixedArray` can not implement `RecursiveIterator`

From: Date: Mon, 28 Feb 2022 05:20:19 +0000
Subject: [php-src] Issue #8156: Classes extending `SplFixedArray` can not implement `RecursiveIterator`
Groups: php.bugs 
Request: Send a blank email to php-bugs+get-240073@lists.php.net to get a copy of this message
Issue: https://github.com/php/php-src/issues/8156 Comment Author: damianwadley I don't mind replying but I don't think there's anything actionable here... > Implementing both Iterator and IteratorAggregate is a problem, because they are identical > behaviors that are interchangeable. They aren't identical behaviors. They're both iterable but they go about it two completely different ways: one of them means the object modifies itself during iteration, and the other means the object remains unchanged because it uses a proxy object to handle iteration (which does gets modified). That self-modification can be a significant problem if you aren't careful. For example, this code ```php <?php function print_directory($iterator) { foreach ($iterator as $file) { if ($file->isDir()) { echo "{$file} is dir containing:\n"; print_directory($file); } else { echo "{$file} is file\n"; } } } $root = new DirectoryIterator("."); print_directory($root); ?> ``` may look fine but it will not work because $root, $iterator, and $file are *all the same object*. Classes using IteratorAggregate don't have that problem (not unless they try to) because the object used for iteration is something separate. > A Fatal error thrown when both Iterator and IteratorAggregate are implemented on the same class > is acceptable. > > A Fatal error thrown when an IteratorAggregate and an interface that extends Iterator is > implemented on the same class is undesired. eg RecursiveIterator I don't see how you can make the first statement and also make the second statement. Iterator and IteratorAggregate are two separate mechanisms for iteration so it logically does not make sense to support both. It doesn't matter where in the inheritance hierarchy Iterator and IteratorAggregate are introduced, the end result is that the resultant class would have support for both mechanisms. And there's no way to "un-implement" an interface. > why is this behavior is not documented, if it is in fact the intended behavior? It is documented. I gave you a link to a section in the PHP 8.0 migration guide where one of the bullet points says exactly this happened: > SplFixedArray is now an IteratorAggregate and not an Iterator. SplFixedArray::rewind(), > SplFixedArray::current(), SplFixedArray::key(), SplFixedArray::next(), and SplFixedArray::valid() > have been removed. In their place, SplFixedArray::getIterator() has been added. Any code which uses > explicit iteration over SplFixedArray must now obtain an Iterator through > SplFixedArray::getIterator(). This means that SplFixedArray is now safe to use in nested loops. Note that SplFixedArray's Changelog incorrectly states IteratorAggregate was added in 8.1 (and I created an issue for that), but the most important documentation to check for large changes like this is still the migration guide.

« previous php.bugs (#240073) next »