Qual interface PHP permite que as propriedades dos objetos sejam acessíveis com a notação de matriz?
-
22-09-2019 - |
Pergunta
Qual interface PHP SPL permite que os objetos façam isso:
$object->month = 'january';
echo $object['month']; // january
$record['day'] = 'saturday';
echo $record->day; // saturday
por exemplo, como em bibliotecas como a doutrina (doutrina_record)
Como faço para implementar isso? Eu tentei usar o ArrayObject, mas eles não se comportam como eu pensei que o faria.
ou seja
$object = new ArrayObject();
$object['a'] = 'test';
$object['a'] == $object->a; // false
EDITAR:
Eu tentei uma implementação sem ossos que chamei de 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);
}
}
Solução
Isso é ArrayAccess
Veja o SourCecode para Doutrine_record
abstract class Doctrine_Record
extends Doctrine_Record_Abstract
implements Countable, IteratorAggregate, Serializable
abstract class Doctrine_Record_Abstract extends Doctrine_Access
e finalmente Doutrina_access
abstract class Doctrine_Access
extends Doctrine_Locator_Injectable
implements ArrayAccess
De docblock
Fornece acesso à matriz e interface de sobrecarga de propriedades para subclasses de doutrina
Um objeto que implementa o ArrayAccess deve ter esses métodos
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 );
Há um exemplo de uso básico no manual do PHP (vinculado acima)
Outras dicas
Você está usando duas coisas diferentes aqui:
A interface ArrayAccess para $a[key]
ehttp://php.net/manual/en/language.oop5.overloading.php por $a->key
O que acontece é
$a[key]
chamará $a->offsetGet(key)
(herdado de ArrayAccess) e $a->key
chamará $a->__get(key)
ou $a->__set(key, val)
(em contextos como $a->key = val
).
Eu acho que você pode lançar objeto e matrizes ..
$object = (object)array('name'=>'aviv');
echo $object->name; // prints aviv
E vice -versa ..
$array= (array)$object;
echo $array['name']; // prints aviv
Você pode implementar sua própria classe, por exemplo
class PropertyTest {
$month;
}
então em uso de código
$object = new PropertyTest;
$object->month = "January";
echo $obejct->month;
Estou respondendo à pergunta usando seu código de exemplo com uma pequena adição:
<?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
Demonstração: https://3v4l.org/nd5nw
ArrayObject
aceita um segundo argumento do construtor, que é
ArrayObject :: std_prop_listAs propriedades do objeto têm sua funcionalidade normal quando acessadas como lista (var_dump, foreach, etc.).
ArrayObject :: Array_AS_PropsAs entradas podem ser acessadas como propriedades (leia e escreva).
Referência: http://php.net/manual/de/class.arrayobject.php