我的应用程序中有一个 Config
类,它加载静态配置设置并将它们解析为数组。
因为我需要在运行时覆盖一些元素,所以我需要通过这样做来访问 Config
类中的公共(public)变量; $config->values['onelevel']['twolevel'] = 'changed';
我想创建一个名为 override
的方法来为我执行此操作,但我不知道什么是最好的方法,因为我的配置文件可能未知 future 嵌套级别的数量。
做类似 $config->onelevel->twolevel = 'changed'
并让 __set 魔术方法处理嵌套的事情会很可爱,但据我所知,它不可能。
执行此操作的最佳方法是什么?
最佳答案
可以随心所欲。
这个例子很大程度上受到了 Zend_Config 的启发。以及 ArrayAccess interface 上的 PHP 文档中给出的示例.
编辑:
有一个小警告:您需要对表示数组的数据调用 toArray()
,将其转换为数组,因为该类在内部需要将数组数据转换为其自身的一个实例,允许使用对象属性运算符访问 ->
:
嗯,这当然不再是必需的,因为它现在实现了 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;
}
}
编辑 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 );
}
}
示例用法:
$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...
关于PHP:修改多维数组的最干净方法?,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/7202784/