PHP:修改多维数组的最干净方法?

标签 php arrays oop multidimensional-array

我的应用程序中有一个 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/

相关文章:

java - 如何从 .t​​xt 文件中读取数字并以单字数字的形式打印出来? IE。 30= 三个零 1= 一

javascript - 更改可观察数组会改变自定义绑定(bind)处理程序、knockoutjs 的可见性

c - 3D 数组的指针算法

php - 在 PHP 中实例化对象后立即使用对象运算符

javascript - JavaScript 中的对象属性 "Previous Value"

javascript - 使用方法扩展类是一个好习惯吗?

php - Objective C 和 PHP 在 Blowfish 算法中生成不同的加密结果

php - CakePHP 将新模型关联添加到现有表

php - 在没有目标 ="_blank"的新页面中提交表单

php - 使用 PHP 使用用户的用户名和密码从外部更新 Facebook 状态