Объект действует как массив?(PHP) - PullRequest
9 голосов
/ 21 сентября 2010

Я видел нечто подобное в ORM:

    $b = new Book();
    $b->limit(5)->get();

    echo 'ID: ' . $b->id . '<br />';
    echo 'Name: ' . $b->title . '<br />';
    echo 'Description: ' . $b->description . '<br />';
    echo 'Year: ' . $b->year . '<br />';

    foreach ($b as $book)
    {
        echo 'ID: ' . $book->id . '<br />';
        echo 'Name: ' . $book->title . '<br />';
        echo 'Description: ' . $book->description . '<br />';
        echo 'Year: ' . $book->year . '<br />';
        echo '<br />';
    }

Как это возможно, что объект действует как массив и объект? Как я могу это сделать? Я надеялся увидеть новый метод __magic или что-то в родительском классе Book, но ничего не смог найти, поэтому в объектах php может быть что-то действительно простое, чего я не знаю.

Есть мысли? Заранее спасибо

Ответы [ 2 ]

12 голосов
/ 21 сентября 2010

Объекты, которые реализуют интерфейс Traversable (через Iterator или IteratorAggregate), поддерживают конструкцию foreach, если вы этоимеется в виду под «действовать как массив».Например:

class theClass implements Iterator {
    // implement iterator here
}

// now you can do
$obj = new theClass;

foreach ($obj as $value) {
    // do something
}
6 голосов
/ 21 сентября 2010

Вам не нужно делать ничего особенного, чтобы использовать foreach с объектами.

Из руководства PHP по итерации объектов :

PHP 5 предоставляет способ определения объектов, поэтому можно выполнять итерацию по списку элементовНапример, оператором foreach.По умолчанию все видимые свойства будут использоваться для итерации.

Пример:

class Foo
{
    public $foo = 1;
    protected $bar = 2;
    private $baz = 3;
}

foreach(new Foo as $prop) echo $prop; // outputs 1 only

Ваш класс не должен реализовывать Traversable, как предложено в другом месте, и на самом деле вышеприведенный класс этого не делает:

var_dump (new Foo instanceof Traversable); // FALSE

Вы можете реализовать один из Iterator или IteratorAggregate , если вам нужно больше контроля над тем, как должна вести себя итерация:

class Foo implements IteratorAggregate
{
    public $foo = 1;
    protected $bar = 2;
    private $baz = 3;

    public function getIterator()
    {
        return new ArrayIterator((array) $this);
    }
}

foreach(new Foo as $prop) echo $prop; // outputs 123

Поскольку Iterator и IteratorAggregate расширяют Traversable, ваш класс теперь также будет экземпляром Traversable, но, как показано выше, для итерации объекта нет необходимости.

var_dump (new Foo instanceof Traversable); // TRUE

Youтакже можно использовать ArrayObject , чтобы объект вел себя как гибрид между классом и объектом.Или вы можете реализовать ArrayAccess , чтобы разрешить доступ к классу в квадратных скобках.Вы также можете создать подкласс класса , один из итераторов , предоставляемый PHP.

Дополнительная информация:

Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...