方法1
通过继承Iterator
接口并实现它的相关方法,就可以实现像循环数组一样 来循环类
<?php
/**
* 类实现foreach的访问
*/
class FileDB implements Iterator
{
public $val = [];
public function __construct($array)
{
if(is_array($array)){
$this->val = $array;
}
}
public function current()
{
$val = current($this->val);
return $val;
}
public function next()
{
$val = next($this->val);
return $val;
}
public function key()
{
$key = key($this->val);
return $key;
}
public function valid()
{
$key = key($this->val);
if($key !== null && $key !==false){
return $key;
}
return false;
}
public function rewind()
{
reset($this->val);
}
}
$arr = [
'name' => 'zhangtian',
'sex' => 'nan',
'height' => '189',
];
$obj = new FileDB($arr);
foreach ($obj as $key => $val){
echo $key."-".$val."\n";
}
方法2
通过继承 IteratorAggregate
接口,并实现getIterator
方法就可以foreach
类实例
<?php
class Test implements IteratorAggregate
{
public $val;
public function __construct($arr)
{
$this->val = $arr;
}
public function getIterator()
{
return new ArrayIterator($this->val);
}
}
$arr = ['zhangtian','weifeng','test'];
$obj = new Test($arr);
var_dump($obj instanceof Iterator);
// 结果为 bool(false)
// 虽然IteratorAggregate可以被当作Iterator使用,但是它不是Iterator
echo count($obj)."\n";
// 结果为 1
// 虽然getIterator的返回对象实现了count方法,
// 但是它不能直接被IteratorAggregate实例使用
echo count($obj->getIterator()); //echo 3
echo "<hr>";
//循环读取数据
foreach ($obj as $key => $val) {
echo $key . "-" . $val . "\n";
}
Iterator
和 IteratorAggregate
的区别和联系
Iterator
接口实现是真正并且底层的迭代器,而IteratorAggregate
是为了方便类使用Iterator
而添加的一个额外接口。它们是两个不同的概念,具体使用的时候应该清楚两者间的差异。差别有以下两点:
-
Iterator接口的实现需要自己手动实现它的5个函数,而IteratorAggregate则不需要这样而只需要实现一个返回Iterator对象的方法。
-
实现了Iterator接口的类是一个Iterator,除了在foreach语句中使用外还可以在其他需要Iterator的环境中使用。而实现IteratorAggregate接口的类只能用于foreach循环,并且如果它返回的Iterator除了这5个方法外还实现了其他方法,不能通过IteratorAggregate类直接使用,而必须用$iteratorAggregate->getIterator()调用那个Iterator来使用。
实例: FileDb类实现foreach逐行遍历文件内容
<?php
/**
* 类实现foreach的访问
*/
class FileDB implements Iterator
{
private $filePath;
private $fp;
private $linePoint; //当前行的指针
public function __construct($filePath)
{
$this->filePath = $filePath;
$this->init();
}
public function init()
{
$this->linePoint = 0 ;
if(is_null($this->fp)){
$this->fp = fopen($this->filePath,'rb');
}
}
/**
* 当前行的数据
* @return bool|mixed|string
*/
public function current()
{
return fgets($this->fp);
}
/**
* 下一行的指针位置
*/
public function next()
{
++$this->linePoint;
}
/**
* 当前的指针位置
* @return mixed
*/
public function key()
{
return $this->linePoint;
}
/**
* 检查是否读到未见末尾
* @return bool
*/
public function valid()
{
return $this->linePoint <= count(file($this->filePath));
}
/**
* 重置文件头,指针指向第一行
*/
public function rewind()
{
$this->init();
$this->next();
}
}
$obj = new FileDB('a.log');
foreach ($obj as $key => $val){
echo $key."-".$val."\n";
}
评论前必须登录!
注册