views:

6393

answers:

7

I have a variable on the global scope that is named ${SYSTEM}, where SYSTEM is a defined constant. I've got a lot of classes with functions that need to have access to this variable and I'm finding it annoying declaring global ${SYSTEM}; every single time.

I tried declaring a class variable: public ${SYSTEM} = $GLOBALS[SYSTEM]; but this results in a syntax error which is weird because I have another class that declares class variables in this manner and seems to work fine. The only thing I can think of is that the constant isn't being recognised.

I have managed to pull this off with a constructor but I'm looking for a simpler solution before resorting to that.

:::EDIT::: The global ${SYSTEM} variable is an array with a lot of other child arrays in it. Unfortunately there doesn't seem to be a way to get around using a constructor...

+1  A: 

The direct specification of member variables can not contain any references to other variables (class {public $membervar = $outsidevar;} is invalid as well). Use a constructor instead.

However, as you are dealing with a constant, why don't you use php's constant or class constant facilities?

phihag
A: 

I'd say the first two things that stand out to me are:

  1. You don't need the brackets around the variable name, you can simply do public $system or public $SYSTEM.
  2. While PHP may not always require it it is standard practice to encapsulate non-numeric array indexes in single or double quotes in case the string you're using becomes a constant at some point.

This should be what you're looking for

class SomeClass {
  public $system = $GLOBALS['system'];
}

You can also use class constants which would instead be

class SomeClass {
  const SYSTEM = $GLOBALS['system'];
}

This can be referenced within the class with 'self::SYSTEM' and externally with 'SomeClass::SYSTEM'.

Steven Surowiec
Does that mean constants > variable names?
E3
In the question, SYSTEM is a constant, not a variable name.
PolyThinker
I don't know what you're talking about but ${SYSTEM} most definitely isn't the same as $SYSTEM...
E3
@E3, are you referring to my comment? I was saying that Steven probably had mistaken SYSTEM as a variable.
PolyThinker
A: 

You could also try the singleton pattern, although to some degree it is frowned upon in OOP circles, it is commonly referred to as the global variable of classes.

<?php
class Singleton {

  // object instance
  private static $instance;

  // The protected construct prevents instantiating the class externally.  The construct can be
  // empty, or it can contain additional instructions...
  protected function __construct() {
    ...
  }

  // The clone and wakeup methods prevents external instantiation of copies of the Singleton class,
  // thus eliminating the possibility of duplicate objects.  The methods can be empty, or
  // can contain additional code (most probably generating error messages in response
  // to attempts to call).
  public function __clone() {
    trigger_error('Clone is not allowed.', E_USER_ERROR);
  }

  public function __wakeup() {
    trigger_error('Deserializing is not allowed.', E_USER_ERROR);
  }

  //This method must be static, and must return an instance of the object if the object
  //does not already exist.
  public static function getInstance() {
    if (!self::$instance instanceof self) { 
      self::$instance = new self;
    }
    return self::$instance;
  }

  //One or more public methods that grant access to the Singleton object, and its private
  //methods and properties via accessor methods.
  public function GetSystemVar() {
    ...
  }
}

//usage
Singleton::getInstance()->GetSystemVar();

?>

This example is slightly modified from wikipedia, but you can get the idea. Try googling the singleton pattern for more information

Asciant
I don't see how this is related to singleton.
PolyThinker
How doesn't it relate? An explanation would seem more appropriate.
Asciant
A: 

You could use a constructor like this:

class Myclass {
  public $classvar; 
  function Myclass() {
    $this->classvar = $GLOBALS[SYSTEM];
  }
}

EDIT: Thanks for pointing out the typo, Peter!

This works for array too. If assignment is not desired, taking the reference also works:

$this->classvar =& $GLOBALS[SYSTEM];

EDIT2: The following code was used to test this method and it worked on my system:

<?php
define('MYCONST', 'varname');
$varname = array("This is varname", "and array?");

class Myclass {
  public $classvar;
  function Myclass() {
    $this->classvar =& $GLOBALS[MYCONST];
  }
  function printvar() {
    echo $this->classvar[0]; 
    echo $this->classvar[1];
  }
};

$myobj = new Myclass;
$myobj->printvar();
?>
PolyThinker
Should that be '$this->classvar = ...'?
too much php
A: 

You're trying to do something really out-of-the-ordinary here, so you can expect it to be awkward. Working with globals is never pleasant, especially not with your dynamic name selection using SYSTEM constant. Personally I'd recommend you use $GLOBALS[SYSTEM] everywhere instead, or ...

$sys = $GLOBALS[SYSTEM];

... if you're going to use it alot.

too much php
+1  A: 

Ok, hopefully I've got the gist of what you're trying to achieve

<?php
    // the global array you want to access
    $GLOBALS['uname'] = array('kernel-name' => 'Linux', 'kernel-release' => '2.6.27-11-generic', 'machine' => 'i686');

    // the defined constant used to reference the global var
    define(_SYSTEM_, 'uname');

    class Foo {

        // a method where you'd liked to access the global var  
        public function bar() {
            print_r($this->{_SYSTEM_});
        }

        // the magic happens here using php5 overloading
        public function __get($d) {
            return $GLOBALS[$d];  
        }

    }

    $foo = new Foo;
    $foo->bar();

?>
frglps
A: 

This is how I access things globally without global.

class exampleGetInstance

{

private static $instance;

public $value1;
public $value2;


private function initialize() 
{
 $this->value1 = 'test value';
    $this->value2 = 'test value2';

}

public function getInstance()
{
 if (!isset(self::$instance))
 {
  $class = __CLASS__;
  self::$instance = new $class();
  self::$instance->initialize();
 }
 return self::$instance;
}

}

$myInstance = exampleGetInstance::getInstance();

echo $myInstance->value1;

$myInstance is now a reference to the instance of exampleGetInstance class.

Syntax