berridgeab Posted October 21, 2013 Share Posted October 21, 2013 Hi, I'm looking to create a basic superglobal class wrapper for the PHP super globals. I don't know how to go about setting nested array keys / values within the object. Here is my basic class wrapper - class superGlobal { protected $superGlobal; public function __construct(array $superGlobal) { $this->superGlobal = $superGlobal; } public function set($value, $arrayKey = null) { if(is_scalar($arrayKey)) { $this->superGlobal[$arrayKey] = $value; } else { $this->superGlobal[] = $value; } } public function get() { return $this->superGlobal; } } A very simple wrapper. Thanks to the addition of array literials in PHP5.5 I can access single or nested array values easily like below so no problem here. $nestedArray = array( "Unnested Array Value", array( "Nested Array Value")); $superGlobal = new \superGlobal($nestedArray); //Outputs "Unnested Array Value" echo $superGlobal->get()[0] //Outputs "Nested Array Value" echo $superGlobal->get()[1][0] However I have no idea how to write a "set" function that can accept a nested key . Any ideas? Currently I have to get the nested array, store it in a temporary variable like below. //Create superglobal object with random nested array and output $superGlobal = new \superGlobal(array()); $superGlobal->set(array(0 => array(0 => array(0 => "Apples"))), "nestedItem"); //Output array echo "<pre>" , print_r($superGlobal->get(), 1) , "</pre>"; //Grab array and store $temporaryStore = $superGlobal->get()['nestedItem']; //Add new value to the nested array $temporaryStore[0][0][1] = "Oranges"; //Now reset the value $superGlobal->set($temporaryStore, "nestedItem"); //Output array echo "<pre>" , print_r($superGlobal->get(), 1) , "</pre>"; Basically I want to cut out the step of having to store the array into a temporary variable, modify it and reassigning it. I could make the variable public, but I would prefer not to. Quote Link to comment Share on other sites More sharing options...
vinny42 Posted October 21, 2013 Share Posted October 21, 2013 It looks like you are creating a registry pattern. Basically I want to cut out the step of having to store the array into a temporary variable, modify it and reassigning it That would mean making the class aware of what you are storing in it, which I feel goes beyong the scope of what a superglobal of registry is supposed to do. I'd feel more comfortable with a "fruitlist" object that you can store in the registry, then you can modify that by getting it from the registry and calling a modifier method on it to replace the element. Quote Link to comment Share on other sites More sharing options...
Solution ignace Posted October 21, 2013 Solution Share Posted October 21, 2013 (edited) untested class RecursiveArrayWrapper extends \ArrayObject { public function offsetGet($offset) { $data = parent::offsetGet($offset); if (is_array($data)) { return new static($data, $this->getFlags(), $this->getIteratorClass()); } return $data; } // add functionality as needed public function merge($array) { if ($array instanceof self) { $array = $array->getArrayCopy(); } $this->exchangeArray(array_merge($this->getArrayCopy(), $array)); return $this; } } $array = new RecursiveArrayWrapper(array( 'foo' => array('bar' => array('bat' => 'baz')) ), ArrayObject::ARRAY_AS_PROPS); var_dump($array->foo->bar->bat); var_dump($array->foo->merge(array('bar' => array('bat' => 'foo')))->bar->bat);Does exactly what you want but instead of calling it something as meaningless as superGlobal, I called it something so that it can be re-used for something more then just as a superGlobal container (which it really wasn't either). This is kinda more what I would call it: class HttpRequest { public $get; public $post; public $cookie; public $session; public $server; public $files; public $env; public $globals; public function __construct() { foreach (array('get', 'post', 'cookie', 'session', 'server', 'files', 'env', 'globals') as $superGlobal) { if (isset(${'_' . strtoupper($superGlobal)})) { $this->$superGlobal = new RecursiveArrayWrapper(${'_' . strtoupper($superGlobal)}, ArrayObject::ARRAY_AS_PROPS); } } } } $request = new HttpRequest; var_dump($request->get->foo); Edited October 21, 2013 by ignace Quote Link to comment Share on other sites More sharing options...
berridgeab Posted October 22, 2013 Author Share Posted October 22, 2013 (edited) Very nice ignace, the HTTPRequest class doesn't get filled but I think thats down to not being able to use variable variables with PHPs superglobals. http://php.net/manual/en/language.variables.variable.php Anyway thats a minor issue, you've gave me some ideas and a direction to follow. Thanks for your response. Edit - Updated HTTPRequest class to get around variable variable issue. class HttpRequest { public $get; public $post; public $cookie; public $session; public $server; public $files; public $env; public function __construct() { foreach (array('get', 'post', 'cookie', 'session', 'server', 'files', 'env') as $superGlobal) { $globals = $GLOBALS; if(isset($globals['_' . strtoupper($superGlobal)])) { $this->$superGlobal = new RecursiveArrayWrapper($globals['_' . strtoupper($superGlobal)], ArrayObject::ARRAY_AS_PROPS); } } } } Edited October 22, 2013 by berridgeab Quote Link to comment Share on other sites More sharing options...
Recommended Posts
Join the conversation
You can post now and register later. If you have an account, sign in now to post with your account.