PHP: Expose 'get' and 'set' for an object with nested associative arrays

I have a class that stores values ​​with a multi-level associative array:

I need to add a way to access and change nested values. Here is a working solution for my problem, but it is rather slow . Is there a better way to do this ?

Note. Using get / set functions is optional, but there should be an effective way to determine the default value.

class Demo {
    protected $_values = array();

    function __construct(array $values) {
        $this->_values = $values;
    }

    public function get($name, $default = null) {
        $token = strtok($name, '.#');
        $node = $this->_values;
        while ($token !== false) {
            if (!isset($node[$token]))
                return $default;
            $node = $node[$token];
            $token = strtok('.#');
        }
        return $node;
    }

    public function set($name, $value) {
        $next_token = strtok($name, '.#');
        $node = &$this->_values;

        while ($next_token !== false) {
            $token = $next_token;
            $next_token = strtok('.#');

            if ($next_token === false) {
                $node[ $token ] = $value;
                break;
            }
            else if (!isset($node[ $token ]))
                $node[ $token ] = array();

            $node = &$node[ $token ];
        }

        unset($node);
    }

}

which will be used as follows:

$test = new Demo(array(
    'simple'  => 27,
    'general' => array(
        0 => array(
            'something'    => 'Hello World!',
            'message'      => 'Another message',
            'special'      => array(
                'number'       => 27
            )
        ),
        1 => array(
            'something'    => 'Hello World! #2',
            'message'      => 'Another message #2'
        ),
    )
));

$simple = $test->get('simple'); // === 27

$general_0_something = $test->get('general#0.something'); // === 'Hello World!'

$general_0_special_number = $test->get('general#0.special.number'); === 27

Note: "general.0.something" matches "general # 0.something", alternative punctuation is for clarity.

+5
4

, , .: -)

, . , , . , . , ? ( " " " " )?

, , ( ), , .

get. , , . .

, , , .

(-), , . , , get.

- :

<?php

class Demo {
    protected $_values = array();
    protected $_valuesByHash = array();

    function createHashMap(&$array, $path = null) {
        foreach ($array as $key => &$value) {
            if (is_array($value)) {
                $this->createHashMap($value, $path.$key.'.');
            } else {
                $this->_valuesByHash[$path.$key] =& $value;
            }
        }
    }

    function __construct(array $values) {
        $this->_values = $values;
        $this->createHashMap($this->_values);

        // Check that references indeed work
        // $this->_values['general'][0]['special']['number'] = 28;
        // print_r($this->_values);
        // print_r($this->_valuesByHash);
        // $this->_valuesByHash['general.0.special.number'] = 29;
        // print_r($this->_values);
        // print_r($this->_valuesByHash);
    }

    public function get($hash, $default = null) {
        return isset($this->_valuesByHash[$hash]) ? $this->_valuesByHash[$hash] : $default;
    }
}


$test = new Demo(array(
    'simple'  => 27,
    'general' => array(
        '0' => array(
            'something'    => 'Hello World!',
            'message'      => 'Another message',
            'special'      => array(
                'number'       => 27
            )
        ),
        '1' => array(
            'something'    => 'Hello World! #2',
            'message'      => 'Another message #2'
        ),
    )
));

$start = microtime(true);

for ($i = 0; $i < 10000; ++$i) {
    $simple = $test->get('simple', 'default');
    $general_0_something = $test->get('general.0.something', 'default');
    $general_0_special_number = $test->get('general.0.special.number', 'default');
}

$stop = microtime(true);

echo $stop-$start;

?>

, (# separator), , .

, , . , 30-40%. , . , , .: -)

+3

, , . PHP ( , ) - .

: ​​ / .

, , . , , 20 .

class Demo extends ArrayObject {
    protected $_default;
    public function __construct($array,$default = null) {
        parent::__construct($array);
        $this->_default = $default;
    }
    public function  offsetGet($index) {
        if (!parent::offsetExists($index)) return $this->_default;
        $ret = parent::offsetGet($index);
        if ($ret && is_array($ret)) {
            parent::offsetSet($index, $this->newObject($ret));
            return parent::offsetGet($index);
        }
        return $ret;
    }
    protected function newObject(array $array=null) {
        return new self($array,$this->_default);
    }
}

$test = new Demo(array(
    'general' => array(
        0 => array(
            'something'    => 'Hello World!'
        )
    )
),'Default Value');

$something = $test['general'][0]['something']; // 'Hello World!'
$notfound = $test['general'][0]['notfound']; // 'Default Value'
+3

- ? get() $values , .

class Demo {
    protected $_values = array();

    public function __construct(array $values) {
        $this->_values = $values;
    }

    public function get($name, $default = null) {
        $parts  = preg_split('/[#.]/', $name);
        if (!is_array($parts) || empty($parts)) {
            return null;
        }

        $value  = &$this->_values;
        foreach ($parts as $p) {
            if (array_key_exists($p, $value)) {
                $value  = &$value[$p];
            } else {
                return null;
            }
        }

        return $value;
    }

    /**
     * setter missing
     */
}

$test = new Demo(array(
    'simple'  => 2,
    'general' => array(
        0 => array(
                'something'    => 'Hello World!',
                'message'      => 'Another message',
                'special'      => array(
                    'number'       => 4
                )
            ),
        1 => array(
                'something'    => 'Hello World! #2',
                'message'      => 'Another message #2'
            )
    )
));

$v = $test->get('simple'); 
var_dump($v);

$v = $test->get('general'); 
var_dump($v);

$v = $test->get('general.0'); 
var_dump($v);

$v = $test->get('general#0'); 
var_dump($v);

$v = $test->get('general.0.something'); 
var_dump($v);

$v = $test->get('general#0.something'); 
var_dump($v);

$v = $test->get('general.0.message'); 
var_dump($v);

$v = $test->get('general#0.message'); 
var_dump($v);

$v = $test->get('general.0.special'); 
var_dump($v);

$v = $test->get('general#0.special'); 
var_dump($v);

$v = $test->get('general.0.special.number'); 
var_dump($v);

$v = $test->get('general#0.special.number'); 
var_dump($v);

$v = $test->get('general.1'); 
var_dump($v);

$v = $test->get('general#1'); 
var_dump($v);

$v = $test->get('general.1.something'); 
var_dump($v);

$v = $test->get('general#1.something'); 
var_dump($v);

$v = $test->get('general.1.message'); 
var_dump($v);

$v = $test->get('general#1.message'); 
var_dump($v);
+1

PHP:

$data = array(
    'general' => array(
         0 => array(
             'something'    => 'Hello World!'
         )
    )
);

Hello World:

echo $data['general'][0]['something'];
0

All Articles