遍历对象

PHP 提供了一种定义对象的方法使其可以通过单元列表来遍历,例如用 foreach 语句。默认情况下,所有可见属性都将被用于遍历。

<?php

class Foo
{
    /**
     * Public property.
     *
     * @var string
     */
    public string $public = 'public';

    /**
     * Protected property.
     *
     * @var string
     */
    protected string $protected = 'protected';

    /**
     * Private property.
     *
     * @var string
     */
    private string $private = 'private';

    /**
     * Print all visibility properties.
     *
     * @param  void
     * @return void
     */
    public function method()
    {
        foreach ($this as $key => $value) {
            var_dump("$key => $value");
        }
    }
}

$foo = new Foo();
foreach ($foo as $key => $value) {
    var_dump("$key => $value");
}
// string(16) "public => public"

$foo->method();
// string(16) "public => public"
// string(22) "protected => protected"
// string(18) "private => private"

更进一步,可以实现 Iterator 接口。可以让对象自行决定如何遍历以及每次遍历时那些值可用。

<?php

class Foo implements Iterator
{
    /**
     * Store an array.
     *
     * @var array
     */
    private array $property;

    /**
     * Store an array to the property.
     *
     * @param  array $array
     * @return void
     */
    public function __construct(array $array)
    {
        $this->property = $array;
    }

    /**
     * Return the current element of the specified property.
     *
     * @param  void
     * @return int
     */
    public function current(): int
    {
        var_dump(__METHOD__);
        return current($this->property);
    }

    /**
     * Advance the internal pointer of the specified property.
     *
     * @param  void
     * @return void
     */
    public function next()
    {
        var_dump(__METHOD__);
        next($this->property);
    }

    /**
     * Return the current key of the specified property.
     *
     * @param  void
     * @return int
     */
    public function key(): int
    {
        var_dump(__METHOD__);
        return key($this->property);
    }

    /**
     * Return the validity of the current position of the specified property.
     *
     * @param  void
     * @return bool
     */
    public function valid(): bool
    {
        var_dump(__METHOD__);
        return current($this->property) !== false;
    }

    /**
     * Set the internal pointer of the specified property to the first element.
     *
     * @param  void
     * @return void
     */
    public function rewind()
    {
        var_dump(__METHOD__);
        reset($this->property);
    }
}

$foo = new Foo([2, 4, 5]);
foreach ($foo as $key => $value) {
    var_dump("$key => $value");
    echo "\r\n";
}
// string(11) "Foo::rewind"
// string(10) "Foo::valid"
// string(12) "Foo::current"
// string(8) "Foo::key"
// string(6) "0 => 2"

// string(9) "Foo::next"
// string(10) "Foo::valid"
// string(12) "Foo::current"
// string(8) "Foo::key"
// string(6) "1 => 4"

// string(9) "Foo::next"
// string(10) "Foo::valid"
// string(12) "Foo::current"
// string(8) "Foo::key"
// string(6) "2 => 5"

// string(9) "Foo::next"
// string(10) "Foo::valid"

可以用 IteratorAggregate 接口以替代实现所有的 Iterator 方法。 IteratorAggregate 只需要实现一个方法 getIterator() ,其应返回一个实现了 Iterator 的类的实例。

<?php

class Foo implements IteratorAggregate
{
    /**
     * Just a test property.
     *
     * @var string
     */
    public string $foo = 'foo';

    /**
     * Just a test property.
     *
     * @var string
     */
    public string $bar = 'bar';

    /**
     * Just a test property.
     *
     * @var string
     */
    public string $baz = 'baz';

    /**
     * Just a test property.
     *
     * @var string
     */
    public string $qux = 'qux';

    /**
     * Return an external iterator.
     *
     * @param  void
     * @return ArrayIterator
     */
    public function getIterator(): ArrayIterator
    {
        return new ArrayIterator($this);
    }
}

$foo = new Foo();
foreach ($foo as $key => $value) {
    var_dump("$key => $value");
}
// string(10) "foo => foo"
// string(10) "bar => bar"
// string(10) "baz => baz"
// string(10) "qux => qux"

results matching ""

    No results matching ""