拋出疑問
php的對象是可以使用諸如foreach
進行循環的。對象的循環,其實就是對像的開放屬性進行的循環。但是在某些框架中,比如laravel中的對象循環,我們發現它並不是對屬性進行遍歷。
- 普通對象:
class abc{
public $a = 'a';
public $b = 'b';
protected $c = 'c';
private $d = 'd';
public function index(){
return 'func';
}
}
$abc = new abc();
foreach($abc as $item){
dump($item);
}
打印結果如下:
"a"
"b"
- laravel集合:
這是使用laravel
查詢的分頁對象
$list = Article::paginate(15);
Illuminate\Pagination\LengthAwarePaginator {#504 ▼
#total: 2
#lastPage: 1
#items: Illuminate\Database\Eloquent\Collection {#510 ▼
#items: array:2 [▼
0 => App\Models\Article {#505 ▶}
1 => App\Models\Article {#497 ▶}
]
}
#perPage: 15
#currentPage: 1
#path: "http://hxsen.houxin.com/category/2"
#query: []
#fragment: null
#pageName: "page"
+onEachSide: 3
#options: array:2 [▶]
}
提示
# 表示保護屬性
+ 表示公開屬性
- 表示私有屬性
但是,對該循環的結果分析發現,它遍歷的並不該對象本身。而是私有的#items
屬性下面的集合。
問題探究
查閱文檔,我們發現最早php5.0的時候就已經支持了一個叫Iterator
接口,並提供了一系列的方法供實現該接口的類定義。
interface Iterator extends Traversable {
public function current();
public function next();
public function key();
public function valid();
public function rewind();
}
說明:
current:返回當前元素
next:向前移動到下一個元素
key: 返回當前元素的鍵
valid:檢查當前位置是否有效
rewind:將迭代器倒回到第一個元素
問題解決
現在修改一下類,實現Iterator
方法
class xyz implements Iterator{
private $_items = array(1,2,3,4,5,6,7);
public $a = 'a';
public $b = 'b';
protected $c = 'c';
private $d = 'd';
public function index(){
return 'func';
}
// Rewind the Iterator to the first element
public function rewind() { reset($this->_items); }
// Return the current element
public function current() { return current($this->_items); }
// Return the key of the current element
public function key() { return key($this->_items); }
// Move forward to next element
public function next() { return next($this->_items); }
// Checks if current position is valid
public function valid() { return ( $this->current() !== false ); }
}
上面的類中的_items
是我們自定義的數組集合。
此時,我們再次對它進行循環
$xyz = new xyz();
foreach($xyz as $value){
dump($value);
}
現在,打印的結果變成了我們的那個_items
數組的元素了。同時,內部的公開屬性,也不在循環之列了。
1
2
3
4
5
6
7
總結說明
PHP中Interator
接口的作用,就是允許對象以自己的方式迭代內部的數據,從而使它可以被循環訪問
當循環執行valid
返回false
時,循環就結束了。