2

I can easily write to and read from a sub-array in the session array.

$_SESSION['a']['b']['c']['value']=123;
$val=$_SESSION['a']['b']['c']['value'];

Instead of hard coding the "location" where the value is written, I would like it to be definable via a string or some other way. The following will obviously not work, but hopefully will better explain the intent.

$prefix="['a']['b']['c']";  //defined in config page, etc
$_SESSION.$prefix.['value']=123;
$val=$_SESSION.$prefix.['value'];

How can this be accomplished?

0

2 Answers 2

3

PropertyAccess

There is an excellent Symfony component for such tasks, named PropertyAccess. You can use it as follows:

$persons = array('a' => array('b' => 5.7));
$accessor = PropertyAccess::createPropertyAccessor();
echo $accessor->getValue($persons, '[a][b]'); // 5.7

You can install it using Composer as described in docs or fetch directly from GitHub.

Custom solution

This is a complete solution, I'm really impressed that it works... but it works! Check the code below, assert()'s demonstrate the usage:

<?php
function arrayPropertyPathGet(array $arr, $path) {
    $parts = explode('.', $path);
    $ret = $arr;
    foreach($parts as $part) {
        $ret = $ret[$part];
        }
    return $ret;
    }

function arrayPropertyPathSet(array &$arr, $path, $value) {
    $parts = explode('.', $path);
    $tmp = &$arr;
    foreach($parts as $part) {
        if(!isset($tmp[$part])) { return false; }
        $tmp = &$tmp[$part];
        }
    $tmp = $value;
    return true;
    }

$test = array('a' => array('b' => 'value'));

assert('value' === arrayPropertyPathGet($test, 'a.b'));
assert(true === arrayPropertyPathSet($test, 'a.b', 'other'));
assert('other' === arrayPropertyPathGet($test, 'a.b'));

Side note

As a theoretical side note (do not use this for anything other than learning purposes) you can experiment with eval(), such as:

eval("$value = $persons['a']['b']");
Sign up to request clarification or add additional context in comments.

11 Comments

Thanks Tomasz. While I don't want to use a new framework right now, I am sure I can look through the Symfony code and see how they do it.
See my updated answer, I provided solution without 3rd party code. But really look into that component, you don't need to use framework to have only it in your project.
Quick note, you don't need the whole framework, symfony is well known for being decoupled, you can use only the PropertyAcces component without the rest of the framework code as stated in the answer
These Symfony2 components were specifically designed to be used anywhere, they're not bound to any framework.
@user1032531 Did my updated answer solve your problem?
|
0

I faced the same problem a few times ago, and as I didn't find any solution, I made one by myself, if that can help you in anyway (only the interesting part) :

class ArrayAccessor {

    private $prefix;

    function setPrefix() {
        $this->prefix = array();
        for ($i = 0; $i < func_num_args(); ++$i) {
            $this->prefix[] =  func_get_arg($i);
        }
    }

    function getFromPrefix(array $array) {
        $tmp_array = $array;
        foreach ($this->prefix as $pre) {
            if (isset ($tmp_array[$pre])) {
                $tmp_array = $tmp_array[$pre];
            } else {
                return null;
            }
        } 
        return $tmp_array;
    }

}



$Access = new ArrayAccessor();
$Access->setPrefix('Hi', 'Toto');

$MyTestArray['Hi']['Toto'] = 'Works';
var_dump ($Access->getFromPrefix($MyTestArray));

$Access->setPrefix('Hi');
var_dump ($Access->getFromPrefix($MyTestArray));

$Access->setPrefix('No');
var_dump ($Access->getFromPrefix($MyTestArray));

Result :

string(5) "Works"

array(1) {
  ["Toto"]=>
  string(5) "Works"
}

NULL

7 Comments

Thanks Clement, Going through your script now. Did you have a method that actually sets the value.
@user1032531 Sets what value ? $Access->getFromPrefix($MyTestArray) = 'My new value'; ?
Setting value would be difficult if not possible in this case - you could try by getting references to array elements to modify them in place, but that won't be nice code to write or maintain.
@user1032531 Ah right my bad, I see what you mean, yes I've a setFromPrefix method too, but can't access the code anymore now, I will edit my answer tonight if you still need it. (And yes, it's a little bit harder that the getter one). Anyway, I think using the Symfony solution sounds much more robust
The last var_dump() should return array('Toto' => 'Works'), don't you think? Anyway, check my answer, I solved both problems in a much simpler manner.
|

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.