我在实现Iterator接口时遇到问题 这是代码:
class User_Model_Users implements Iterator, Countable
{
protected $_count;
protected $_gateway;
protected $_resultSet;
public function __construct($results, $gateway)
{
$this->setGateway($gateway);
$this->_resultSet = $results;
}
public function setGateway(User_Model_UserGateway $gateway)
{
$this->_gateway = $gateway;
return $this;
}
public function getGateway()
{
return $this->_gateway;
}
public function count()
{
if (null === $this->_count) {
$this->_count = count($this->_resultSet);
}
return $this->_count;
}
public function current()
{
if ($this->_resultSet instanceof Iterator) {
$key = $this->_resultSet->key();
} else {
$key = key($this->_resultSet);
}
$result = $this->_resultSet [$key];
if (!$result instanceof User_Model_User) {
$gateway = $this->getGateway();
$result = $gateway->createUser($result);
$this->_resultSet [$key] = $result;
}
return $result;
}
public function key()
{
return key($this->_resultSet);
}
public function next()
{
return next($this->_resultSet);
}
public function rewind()
{
return reset($this->_resultSet);
}
public function valid()
{
return (bool) $this->current();
}
}
作为$ result我提供了Zend_Db_Table_Rowset,但它也可以是其他对象或数组。 如何修复此代码以便我在foreach循环中工作? 我没有得到任何错误,因为它是一个无限循环。
答案 0 :(得分:1)
疯狂猜测(还没有真正研究过代码):
由于您执行valid()是
public function valid()
{
return (bool) $this->current();
}
当没有更多元素时,你应该确保current()返回false
public function current()
{
if ($this->_resultSet instanceof Iterator) {
$key = $this->_resultSet->key();
} else {
$key = key($this->_resultSet);
}
if ( is_null($key) ) { // could also be is_null($key)||false===$key, not sure...
return false;
}
$result = $this->_resultSet[$key];
if (!$result instanceof User_Model_User) {
$gateway = $this->getGateway();
$result = $gateway->createUser($result);
$this->_resultSet[$key] = $result;
}
return $result;
}
和btw:你的函数key()没有像current()那样实现instanceof Iterator
的情况。
测试脚本:
<?php
class User_Model_Users implements Iterator, Countable
{
protected $_count;
protected $_gateway;
protected $_resultSet;
public function __construct($results, $gateway)
{
$this->setGateway($gateway);
$this->_resultSet = $results;
$this->_count = null;
}
public function setGateway(User_Model_UserGateway $gateway)
{
$this->_gateway = $gateway;
return $this;
}
public function getGateway()
{
return $this->_gateway;
}
public function count()
{
if ( is_null($this->_count) ) {
$this->_count = count($this->_resultSet);
}
return $this->_count;
}
public function current()
{
if ($this->_resultSet instanceof Iterator) {
$key = $this->_resultSet->key();
} else {
$key = key($this->_resultSet);
}
if ( is_null($key) ) {
return false;
}
$result = $this->_resultSet[$key];
if (!$result instanceof User_Model_User) {
$gateway = $this->getGateway();
$result = $gateway->createUser($result);
$this->_resultSet[$key] = $result;
}
return $result;
}
public function key()
{
return key($this->_resultSet);
}
public function next()
{
return next($this->_resultSet);
}
public function rewind()
{
return reset($this->_resultSet);
}
public function valid()
{
return (bool) $this->current();
}
}
class User_Model_User {
protected $x, $y;
public function __construct($x, $y) {
$this->x = $x;
$this->y = $y;
}
}
class User_Model_UserGateway {
protected $id;
public function __construct() {
$this->id = time();
}
public function createUser($x) {
echo "User_Model_UserGateway::createUser($x)\n";
return new User_Model_User($x, $this->id);
}
}
$a = array('a', 'b', 'c', 'd');
$users = new User_Model_Users($a, new User_Model_UserGateway);
foreach($users as $u) {
print_r($u);
}
打印
User_Model_UserGateway::createUser(a)
User_Model_User Object
(
[x:protected] => a
[y:protected] => 1311167311
)
User_Model_UserGateway::createUser(b)
User_Model_User Object
(
[x:protected] => b
[y:protected] => 1311167311
)
User_Model_UserGateway::createUser(c)
User_Model_User Object
(
[x:protected] => c
[y:protected] => 1311167311
)
User_Model_UserGateway::createUser(d)
User_Model_User Object
(
[x:protected] => d
[y:protected] => 1311167311
)