Какой интерфейс PHP позволяет свойствам объектов быть доступными с обозначениями массива? - PullRequest
2 голосов
/ 22 февраля 2010

Какой интерфейс PHP SPL позволяет объектам делать это:

$object->month = 'january';
echo $object['month']; // january

$record['day'] = 'saturday';
echo $record->day; // saturday

например. например, в таких библиотеках, как Doctrine (Doctrine_Record)

как мне это реализовать? Я пытался использовать ArrayObject, но они не ведут себя так, как я думал.

т.е.

$object = new ArrayObject();
$object['a'] = 'test';
$object['a'] == $object->a; // false

EDIT:

Я попытался использовать базовую реализацию, которую я назвал Arrayable.

class Arrayable implements ArrayAccess
{
    protected $container = array();

    # implement ArrayAccess methods to allow array notation 
    # $object = new Arrayable();
    # $object['value'] = 'some data';

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

    function offsetGet($offset)
    {
        return $this->container[$offset];
    }

    function offsetSet($offset, $value)
    {
        $this->container[$offset] = $value;
    }

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

    # now, force $object->value to map to $object['value'] 
    # using magic methods

    function __set($offset, $value)
    {
        $this->offsetSet($offset, $value);
    }

    function __get($offset)
    {
        return $this->offsetGet($offset); 
    }
}

Ответы [ 5 ]

4 голосов
/ 22 февраля 2010

Это ArrayAccess

См. исходный код для Doctrine_Record

abstract class Doctrine_Record 
    extends Doctrine_Record_Abstract 
    implements Countable, IteratorAggregate, Serializable

и Doctrine_Record_Abstract

abstract class Doctrine_Record_Abstract extends Doctrine_Access

и наконец Doctrine_Access

abstract class Doctrine_Access 
    extends Doctrine_Locator_Injectable 
    implements ArrayAccess

Из ДокБлока

Предоставляет доступ к массиву и интерфейс перегрузки свойств для подклассов Doctrine


Объект, реализующий ArrayAccess, должен иметь эти методы

abstract public boolean offsetExists  ( mixed $offset  );
abstract public mixed offsetGet ( mixed $offset );
abstract public void offsetSet ( mixed $offset , mixed $value );
abstract public void offsetUnset ( mixed $offset );

В руководстве по PHP приведен основной пример использования (ссылка выше)

3 голосов
/ 22 февраля 2010

Вы используете две разные вещи здесь:

Интерфейс ArrayAccess для $a[key] и http://php.net/manual/en/language.oop5.overloading.php для $a->key

Что происходит, это

$a[key] вызовет $a->offsetGet(key) (унаследовано от ArrayAccess), а $a->key вызовет $a->__get(key) или $a->__set(key, val) (в таких контекстах, как $a->key = val).

0 голосов
/ 27 апреля 2017

Я отвечаю на вопрос, используя ваш пример кода с небольшим дополнением:

<?php
$object = new ArrayObject([], ArrayObject::ARRAY_AS_PROPS);

$object['a'] = 'test';
var_dump($object['a'] == $object->a); // expected: bool(true)

$object->month = 'january';
echo $object['month'];               // expected: january

$object['day'] = 'saturday';
echo $object->day;                   // expected: saturday

Демо : https://3v4l.org/Nd5NW


ArrayObject принимает второй аргумент конструктора, который является либо

  • ArrayObject :: STD_PROP_LIST Свойства объекта имеют свои обычные функциональные возможности при доступе в виде списка (var_dump, foreach и т. Д.).

  • ArrayObject :: ARRAY_AS_PROPS Записи могут быть доступны как свойства (чтение и запись).

Ссылка : http://php.net/manual/de/class.arrayobject.php

0 голосов
/ 22 февраля 2010

Вы можете реализовать свой собственный класс например

class PropertyTest {
 $month;
}

затем в коде используйте

$object = new PropertyTest;
$object->month = "January";
echo $obejct->month;
0 голосов
/ 22 февраля 2010

Я думаю, что вы можете разыгрывать объекты и массивы ..

$object = (object)array('name'=>'aviv');
echo $object->name; // prints aviv

И наоборот ..

$array= (array)$object;
echo $array['name']; // prints aviv
...