实现迭代器循环的类

时间:2011-07-20 11:54:36

标签: php zend-framework

我在实现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循环中工作? 我没有得到任何错误,因为它是一个无限循环。

1 个答案:

答案 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
)