Jack Nicholson Jack Nicholson - 4 months ago 20
PHP Question

Set/Remove for multidimentional array in symfony/httpfoundation

I'm using httpfoundation https://github.com/symfony/http-foundation

I am replacing all

$_SESSION
s with this.

I.e.

$_SESSION['user'] = 'foo'
becomes
$this->Session->set('user', 'foo');

Using the session class.




I am having problems using this with multidimentional arrays.

I can get data okay by doing this:

$this->Session->get('user')['group']['id']


However when I want to set/remove a deep array to a value I have no way of doing so?

$this->Session->set(array('user' => array('group' => 'id')), 200); // Errors

$this->Session->remove(array('form_data' => 'test')); // Errors


Surely there is a clean way of doing this? I don't think it's even possible to set a deep array value using this httpfoundation session jargon.

These seems to be the only methods I can use:

all()
keys()
replace()
add()
get()
set()
has()
remove()


Shout if I'm not clear enough, cheers




New methods following Matt's answer.

Set values for testing
$Session->set( 'test', array('test1' => array('test2' => array('test3' => 'test4') )) );


Run methods
$Session->setDeep('test', array('test1', 'test2', 'test3'), 'flip');

$Session->removeDeep('test', array('test1', 'test2', 'test3'));


Methods are:

/**
* Removes a deep variable item
* @param string $key Top-most array key value
* @param array $path one-dimentional array of path: array('user', 'group', 'id')
*/
public function removeDeep($key, $path)
{
$new_arr = $this->get($key);
$depth = count($path);

switch ($depth) {
case 1:
return false;
break;
case 2:
unset( $new_arr[$path[0]][$path[1]] );
break;
case 3:
unset( $new_arr[$path[0]][$path[1]][$path[2]] );
break;
case 4:
unset( $new_arr[$path[0]][$path[1]][$path[2]][$path[3]] );
break;
}
$this->set($key, $new_arr);
}

/**
* Sets a deep variable item
* @param string $key Top-most array key value
* @param array $path one-dimentional array of path: array('user', 'group', 'id')
* @param mixed $value The value you will set the path to
*/
public function setDeep($key, $path, $value)
{
$new_arr = $this->get($key);
$depth = count($path);

switch ($depth) {
case 1:
return false;
break;
case 2:
$new_arr[$path[0]][$path[1]] = $value;
break;
case 3:
$new_arr[$path[0]][$path[1]][$path[2]] = $value;
break;
case 4:
$new_arr[$path[0]][$path[1]][$path[2]][$path[3]] = $value;
break;
}
$this->set($key, $new_arr);
}

Answer

Think of the first parameter of set as the key to the top-level session array. Pass a string as the key. Instead of

$this->Session->set(array('user' => array('group' => 'id')), 200);

you want

$this->Session->set('user', array('group' => array('id' => 200)));

Keep in mind this means if you want to change an individual value you must get the full array, change the value, and set it all again:

$user = $session->get('user');
$user['group']['id'] = 300;
$session->set('user', $user);

An interesting change to the Session class would be to extend PHP's ArrayObject so you could get and set deep values just like a native array. You could always extend Session and do this yourself.