Es posible hacer lo que quiera.
Este ejemplo está ampliamente inspirado en Zend_Config y el ejemplo dado en los documentos PHP en el ArrayAccess interface.
edición:
Con una pequeña salvedad: es necesario llamar a
toArray()
en los datos que representan una matriz, para convertirlo en una matriz, como la clase necesita internamente para convertir datos de la matriz a una instancia de sí mismo, a permitir el acceso con el operador de propiedad del objeto
->
:
Eh, eso ya no es necesario, por supuesto, ya que ahora implementa ArrayAccess.;-)
/editar
class Config
implements ArrayAccess
{
protected $_data;
public function __construct(array $data)
{
foreach($data as $key => $value)
{
$this->$key = $value;
}
}
public function __get($key)
{
return $this->offsetGet($key);
}
public function __isset($key)
{
return $this->offsetExists($key);
}
public function __set($key, $value)
{
$this->offsetSet($key, $value);
}
public function __unset($key)
{
$this->offsetUnset($key);
}
public function offsetSet($offset, $value)
{
$value = is_array($value) ? new self($value) : $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 toArray()
{
$array = array();
$data = $this->_data;
foreach($data as $key => $value)
{
if($value instanceof Config)
{
$array[ $key ] = $value->toArray();
}
else
{
$array[ $key ] = $value;
}
}
return $array;
}
}
editar 2:
La clase Config
incluso se puede simplificar en gran medida mediante la extensión de ArrayObject
. Como beneficio adicional, también puedes convertirlo en una matriz adecuada.
class Config
extends ArrayObject
{
protected $_data;
public function __construct(array $data)
{
parent::__construct(array(), self::ARRAY_AS_PROPS);
foreach($data as $key => $value)
{
$this->$key = $value;
}
}
public function offsetSet($offset, $value)
{
$value = is_array($value) ? new self($value) : $value;
return parent::offsetSet($offset, $value);
}
}
Ejemplo de uso:
$configData = array(
'some' => array(
'deeply' => array(
'nested' => array(
'array' => array(
'some',
'data',
'here'
)
)
)
)
);
$config = new Config($configData);
// casting to real array
var_dump((array) $config->some->deeply->nested->array);
$config->some->deeply->nested->array = array('new', 'awsome', 'data', 'here');
// Config object, but still accessible as array
var_dump($config->some->deeply->nested->array[ 0 ]);
$config[ 'some' ][ 'deeply' ][ 'nested' ][ 'array' ] = array('yet', 'more', 'new', 'awsome', 'data', 'here');
var_dump($config[ 'some' ][ 'deeply' ][ 'nested' ][ 'array' ]);
$config[ 'some' ][ 'deeply' ][ 'nested' ][ 'array' ][] = 'append data';
var_dump($config[ 'some' ][ 'deeply' ][ 'nested' ][ 'array' ]);
var_dump(isset($config[ 'some' ][ 'deeply' ][ 'nested' ][ 'array' ]));
unset($config[ 'some' ][ 'deeply' ][ 'nested' ][ 'array' ]);
var_dump(isset($config[ 'some' ][ 'deeply' ][ 'nested' ][ 'array' ]));
// etc...
Tal vez ese tipo de datos no puede ser representado por la palabra "config"; guárdelo en el DB – Dor
¿Por qué eligió la respuesta de ErikPerik como la mejor respuesta cuando mi respuesta cumple con los requisitos de su pregunta más de cerca? No es que no quiera otorgar puntos de representante de ErikPerik. Solo tengo curiosidad de por qué sentiste que su respuesta fue la mejor respuesta. –
Originalmente pensé que su solución estaba bastante limpia hasta que vi la versión actualizada de la tuya. ¡Utilizar el 'ArrayObject' es algo que nunca he hecho antes, definitivamente necesito buscarlo! – Industrial