Jump to content

PHP SuperGlobal Class Wrapper


berridgeab
Go to solution Solved by ignace,

Recommended Posts

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.

 

Link to comment
Share on other sites

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.

Link to comment
Share on other sites

  • Solution

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 by ignace
Link to comment
Share on other sites

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 by berridgeab
Link to comment
Share on other sites

This thread is more than a year old. Please don't revive it unless you have something important to add.

Join the conversation

You can post now and register later. If you have an account, sign in now to post with your account.

Guest
Reply to this topic...

×   Pasted as rich text.   Restore formatting

  Only 75 emoji are allowed.

×   Your link has been automatically embedded.   Display as a link instead

×   Your previous content has been restored.   Clear editor

×   You cannot paste images directly. Upload or insert images from URL.

×
×
  • Create New...

Important Information

We have placed cookies on your device to help make this website better. You can adjust your cookie settings, otherwise we'll assume you're okay to continue.