The content of this article is about the understanding of IteratorIterator in php (code examples). It has certain reference value. Friends in need can refer to it. I hope it will be helpful to you.
Recently I have started tinkering with the source code of laravel again. I have almost forgotten it after not using it for more than a year. Every time I look at it, I will start from it. I learned a lot in middle school. If you don’t understand something, just look it up in the manual. I saw the part that loads the configuration file (config/*.php). The spl class library and interface are used extensively in the code. Today I will talk about the IteratorIterator class. There is too little information on the Internet, and I am not very smart. I have done it several times. Genius has some clues, and the following is my personal understanding of it.
IteratorIterator is an iterator wrapper, and of course it is also an iterator itself. It (assuming it is called Outer) must pass in an iterator instance that implements the Traversable interface type (assuming it is called Inner) when instantiating it. Of course, you can get this incoming iterator parameter Inner through the getInnerIterator method of Outer. You can process the internal iterator Inner through Outer's rewind(), next(), valid(), current() and key() methods.
In the process of traversing Outer, Outer just rewind(), next(), valid(), current() and key() Any call is forwarded to the internal iterator Inner.
Outer can wrap the results returned by forwarding, but this will not have any impact on Inner.
<?php namespace young;class InnerIterator implements \Iterator{ private $dates; private $position; public function __construct($dates = []) { $this->dates = $dates; $this->position = 0; } public function rewind() { echo 'call ' . __METHOD__ . '<br>'; reset($this->dates); } public function valid() { echo 'call ' . __METHOD__ . '<br>'; if ($this->position >= count($this->dates)) { # code... return false; } return true; } public function current() { echo 'call ' . __METHOD__ . '<br>'; return $this->dates[$this->position]; } public function key() { echo 'call ' . __METHOD__ . '<br>'; return $this->position; } public function next() { echo 'call ' . __METHOD__ . '<br>'; ++$this->position; }}class OuterIterator extends \IteratorIterator{ function rewind() { echo __METHOD__ . '<br>'; return parent::rewind(); } function valid() { echo __METHOD__ . '<br>'; return parent::valid(); } function current() { echo __METHOD__ . '<br>'; return parent::current() . '_suffix'; } function key() { echo __METHOD__ . '<br>'; return parent::key() ; } function next() { echo __METHOD__ . '<br>'; return parent::next() ; } function getInnerIterator() { echo __METHOD__ . '<br>'; return parent::getInnerIterator(); }}$tmpArr = array( '2018-10-01', '2018-10-02', //'2018-10-03',);$inner = new InnerIterator($tmpArr);$outer = new OuterIterator($inner);foreach ($outer as $key => $value) { # code... echo $key , '=>' , $value . '<hr>';}
young\OuterIterator::rewind
call young\InnerIterator::rewind call young\InnerIterator::valid call young\InnerIterator::current call young\InnerIterator::key
young\OuterIterator::valid young\OuterIterator::current young\OuterIterator::key 0=>2018-10-01_suffix young\OuterIterator::next
call young\InnerIterator::next call young\InnerIterator::valid call young\InnerIterator::current call young\InnerIterator::key
young\OuterIterator::valid young\OuterIterator::current young\OuterIterator::key 1=>2018-10-02_suffix young\OuterIterator::next
call young\InnerIterator::next call young\InnerIterator::valid
young\OuterIterator::valid object(young\InnerIterator)#1 (2) { [“dates”:“young\InnerIterator”:private]=> array(2) { [0]=> string(10) “2018-10-01” [1]=> string(10) “2018-10-02” } [“position”:“young\InnerIterator”:private]=> int(2) }
Every time Outer The iteration will first call its own method and then forward it to Inner.
The return value of Outer's internal method is based on the return of Inner relative to the method.
You can perform logical processing on the return value of Inner in the Outer method.
When Inner's valid returns false, the outer Outer will also stop iterating.
Modification of the return value by the method in Outer will not affect Inner.
The method in Outer will not execute the getInnerIterator method during the iteration process. It is just a calling interface to get the Inner method.
I saw such doubts when I was browsing information on the Internet
//假如这里还是使用了上面的两个类代码 <?php namespace young; class InnerIterator implements \Iterator { //code 这里的代码假如和上面的一样 } class OuterIterator extends \IteratorIterator { //code 这里的代码假如和上面的一样 } $outer->valid(); //false $outer->current(); // _suffix 问题一 $outer->rewind(); $outer->valid(); //true $outer->current(); //2018-10-01_suffix $outer->next() $outer->rewind(); $outer->current(); //2018-10-02_suffix 问题二
There are two questions here,
Question one, why current has no value and valid is false
Question two, why after next and rewind, current is the second value
From the above running results, we can see that $outer does not execute rewind, and $inner will not execute either, so valid returns false, current is null, and _suffix is just spliced by itself.
The second problem is also very strange. I just discovered it. As long as the pointer of $inner moves forward, it cannot go back. That is to say, the position attribute of $inner becomes 1 after the first next. Even if you rewind, the position is still 1, which is a bit confusing. . .
So if you perform the $outer traversal operation, there will be no value output in the second pass. Even if the rewind operation is performed in the second pass, this operation will be useless in the second pass~~~
The above is the detailed content of Understanding of IteratorIterator in php (code example). For more information, please follow other related articles on the PHP Chinese website!