Ind*_*ial 6 php arrays oop multidimensional-array
我的Config应用程序中有一个类,它加载静态配置设置并将它们解析为数组.
由于我需要在运行时覆盖一些元素,我需要Config通过执行此操作来访问-class中的公共变量;$config->values['onelevel']['twolevel'] = 'changed';
我想创建一个override为我做这个调用的方法,但是我无法理解这是最好的方法,因为我的配置文件将来可能会有未知数量的嵌套级别.
做一些类似的事情$config->onelevel->twolevel = 'changed'并让__set魔法方法来处理嵌套会很可爱,但从我所知道的情况来看,这是不可能的.
最好的方法是什么?
你可以做你想做的事.
这个例子受到Zend_Config和ArrayAccess接口上PHP文档中给出的示例的启发.
编辑:
有一个小警告:你需要调用toArray()表示数组的数据,将其转换为数组,因为类内部需要将数组数据转换为自身的实例,以允许使用object属性操作符进行访问->:
呃,当然不再需要了,因为它现在实现了ArrayAccess.;-)
/编辑
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;
}
}
Run Code Online (Sandbox Code Playgroud)
编辑2:
将Config类甚至可以大大延长简化ArrayObject.作为额外的好处,您也可以将其转换为适当的数组.
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 );
}
}
Run Code Online (Sandbox Code Playgroud)
用法示例:
$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...
Run Code Online (Sandbox Code Playgroud)
我也有这个问题,我用这个代码解决了这个问题.但它基于API,如:Config::set('paths.command.default.foo.bar').
<?php
$name = 'paths.commands.default';
$namespaces = explode('.', $name);
$current = &$this->data; // $this->data is your config-array
foreach ( $namespaces as $space )
{
$current = &$current[$space];
}
$current = $value;
Run Code Online (Sandbox Code Playgroud)
它只是循环遍历数组并使用引用变量保持当前值的跟踪.