PHP ArrayObject внутренняя работа - PullRequest
3 голосов
/ 08 февраля 2012

Где я могу найти полный исходный код ArrayObject (в PHP)?

Что я не понимаю, так это то, почему вы можете использовать «стрелку» при добавлении элемента в ArrayObject, например:

$a = new ArrayObject();
$a['arr'] = 'array data';                             
$a->prop = 'prop data';  //here it is

Вы видите, $a->prop = 'prop data'; используется.

Есть ли какой-нибудь магический метод или что использовалось, и как PHP знает, например, что $a['prop'] и $a->prop означают одно и то же? (в этом контексте)

1 Ответ

2 голосов
/ 08 февраля 2012

Да, это волшебство, и это может быть выполнено непосредственно в PHP.Взгляните на Перегрузка http://www.php.net/manual/en/language.oop5.overloading.php

Вы можете использовать __get() и __set в классе, чтобы сделать это.Чтобы объекты вели себя как массивы, вы должны реализовать http://www.php.net/manual/en/class.arrayaccess.php

Это мой пример кода:

<?php
class MyArrayObject implements Iterator, ArrayAccess, Countable
{
    /**  Location for overloaded data.  */
    private $_data = array();

    public function __set($name, $value)
    {
        $this->_data[$name] = $value;
    }

    public function __get($name)
    {
        if (array_key_exists($name, $this->_data)) {
            return $this->_data[$name];
        }

        $trace = debug_backtrace();
        trigger_error(
            'Undefined property via __get(): ' . $name .
            ' in ' . $trace[0]['file'] .
            ' on line ' . $trace[0]['line'],
            E_USER_NOTICE);
        return null;
    }

    /**  As of PHP 5.1.0  */
    public function __isset($name)
    {
        return isset($this->_data[$name]);
    }

    /**  As of PHP 5.1.0  */
    public function __unset($name)
    {
        unset($this->_data[$name]);
    }

    public function offsetSet($offset, $value) {
        if (is_null($offset)) {
            $this->_data[] = $value;
        } else {
            $this->_data[$offset] = $value;
        }
    }

    public function offsetExists($offset) {
        return isset($this->_data[$offset]);
    }

    public function offsetUnset($offset) {
        unset($this->_data[$offset]);
    }

    public function offsetGet($offset) {
        return isset($this->_data[$offset]) ? $this->_data[$offset] : null;
    }
    public function count(){
        return count($this->_data);
    }
    public function current(){
        return current($this->_data);
    }
    public function next(){
        return next($this->_data);
    }
    public function key(){
        return key($this->_data);
    }
    public function valid(){
        return key($this->_data) !== null;
    }
    public function rewind(){
        reset($this->_data);
    }
}

Вместо current($a), next($a) используйте $a->current(), $a->next()

...