简体   繁体   English

PHP Iterator接口:current()返回基础数组,而不是第一个值

[英]PHP Iterator interface: current() returns underlying array instead of first value

I'm creating a class that implements Iterator and ArrayAccess . 我正在创建一个实现IteratorArrayAccess The iterator tests are failing. 迭代器测试失败。 When I do a print_r() on current($object) , I get the underlying array, not the first object. 当我在current($object) print_r()上执行print_r()时,我得到了基础数组,而不是第一个对象。

The code below is a sample from my actual class that demonstrates the issue. 下面的代码是我实际班级中的一个示例,它演示了该问题。 This is the first time I have implemented Iterator in one of my classes, so I'm probably doing this wrong somewhere. 这是我第一次在一个类中实现Iterator ,所以我可能在某个地方做错了。 What do I need to change to make the iterator work properly? 为了使迭代器正常工作,我需要更改什么?

Code: 码:

class Collection implements \ArrayAccess, \Iterator
{
    private $_array = array();

    public function __invoke() { return $this->_array; }
    public function offsetExists($offset) { return array_key_exists($offset, $this->_array); }
    public function offsetGet($offset) { return $this->_array[$offset]; }
    public function offsetSet($offset, $value) { $this->_array[$offset] = $value; }
    public function offsetUnset($offset) { unset($this->_array[$offset]); }
    public function current() { return current($this->_array); }
    public function key() { return key($this->_array); }
    public function next() { return next($this->_array); }
    public function rewind() { return reset($this->_array); }
    public function valid() { return is_null(key($this->_array)); }
}

class TemporaryTest extends \PHPUnit\Framework\TestCase
{

    private $_test_object;

    public function setUp()
    {
        $this->_test_object = new Collection();
        $this->_test_object['alpha'] = 'blah';
        $this->_test_object['beta'] = 'yada';
        $this->_test_object['gamma']  = 'woot';
    }

    public function testIteratorOnInternalArray()
    {
        $o = $this->_test_object;
        $a = $o();
        $this->assertEquals('blah', current($a));
        $this->assertEquals('yada', next($a));
        $this->assertEquals('woot', next($a));
    }

    public function testIterator()
    {
        print_r(current($this->_test_object));
        $this->assertEquals('blah', current($this->_test_object));
        $this->assertEquals('yada', next($this->_test_object));
        $this->assertEquals('woot', next($this->_test_object));
        $this->assertFalse($this->_test_object->valid());
        reset($this->_test_object);
        $this->assertEquals('blah', current($this->_test_object));
    }

    public function testForEach()
    {
        $actual = array();
        foreach ($this->_test_object as $key => $value) { $actual[$key] = $value; }
        $this->assertEquals(array('alpha' => 'blah', 'beta' => 'yada','gamma' =>  'woot'), $actual);
    }
}

Unit test output: 单元测试输出:

.FArray
(
    [alpha] => blah
    [beta] => yada
    [gamma] => woot
)
F                                                                 3 / 3 (100%)

There were 2 failures:

1) TemporaryTest::testIterator
Array (...) does not match expected type "string".

/Users/mac/Projects/NetShapers/Gears/core/Tests/Unit/TemporaryTest.php:83

2) TemporaryTest::testForEach
Failed asserting that two arrays are equal.
--- Expected
+++ Actual
@@ @@
 Array (
-    'alpha' => 'blah'
-    'beta' => 'yada'
-    'gamma' => 'woot'
 )

/Users/mac/Projects/NetShapers/Gears/core/Tests/Unit/TemporaryTest.php:97

What did you expect? 您期望什么?

When you call current($a) you actually call system function current() on your collection, not the internal method Collection::current() . 调用current($a) ,实际上是在集合上调用系统函数current() ,而不是内部方法Collection::current()

Just calll it like this to get what you want: 像这样调用它就可以得到您想要的:

$this->assertEquals('blah', $a->current());

These methods would be called automatically by the system if you could use your collection in foreach for example. 例如,如果您可以在foreach使用您的集合,则系统会自动调用这些方法。


Additional fixes after comment. 评论后的其他修复。

You have an error in valid method, that's why foreach fails for you. 您的valid方法有误,这就是为什么foreach对您失败的原因。

Declaration should look like that: 声明应如下所示:

public function valid() 
{ 
    return !is_null(key($this->_array));
}

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM