views:

281

answers:

4

Which PHP SPL interface allows objects to do this:

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

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

e.g. such as in libraries like Doctrine (Doctrine_Record)

how do I implement this? I've tried using ArrayObject, but they don't behave as I thought they would.

i.e.

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

EDIT:

I tried a barebone implementation that I called 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); 
    }
}
+3  A: 

It's ArrayAccess

See the sourcecode for Doctrine_Record

abstract class Doctrine_Record 
    extends Doctrine_Record_Abstract 
    implements Countable, IteratorAggregate, Serializable

and Doctrine_Record_Abstract

abstract class Doctrine_Record_Abstract extends Doctrine_Access

and finally Doctrine_Access

abstract class Doctrine_Access 
    extends Doctrine_Locator_Injectable 
    implements ArrayAccess

From DocBlock

Provides array access and property overload interface for Doctrine subclasses


An object implementing ArrayAccess has to have these methods

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 );

There is a basic usage example in the PHP manual (linked above)

Gordon
http://php.net/manual/en/class.arrayaccess.php
Stephen Melrose
A: 

I think you can cast object and arrays..

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

And vise versa ..

$array= (array)$object;
echo $array['name']; // prints aviv
aviv
+2  A: 

You are using two different things here:

The ArrayAccess interface for $a[key] and http://php.net/manual/en/language.oop5.overloading.php for $a->key

What happens is

$a[key] will call $a->offsetGet(key) (inherited from ArrayAccess) and $a->key will call $a->__get(key) or $a->__set(key, val) (in contexts like $a->key = val).

Larry_Croft
A: 

You can implement your own class e.g.

class PropertyTest {
 $month;
}

then in code use

$object = new PropertyTest;
$object->month = "January";
echo $obejct->month;
LnDCobra
The OP wants to know how to access the object with array notation, e.g. `$object['month']` in addition to `$object->month`.
Gordon