adam at bregenzer dot net
Adam BregenzerStatic properties in a class are properties that belong to the class, not any instance of the class. Here you will see a very simple way to implement static properties in a class as well as for any class inherited by it.
Static properties can be a very useful OO tool to have in your classes. These properties are associated with the class itself, instead of any particular instance. In PHP 4.x it is not possible to have static properties natively in a class, but there is a very simple way to add them. Defining the following function inside of a class will make it possible to retrieve static properties:
function & getStaticProperty($var) {
static $static_properties;
return $static_properties[$var];
}
To retrieve a static property you do the following:
$static_foo_bar =& Foo::getStaticProperty('bar');
Now $static_foo_bar
is a reference to the static property bar
in the Foo
class. If you put getStaticProperty()
in a base class and derive other classes from it then they will all gain the benefits of static properties without having to put the above code in every class:
class Object {
function & getStaticProperty($var) {
static $static_properties;
return $static_properties[$var];
}
}
class Foo extends Object {
}
$static_foo_bar =& Foo::getStaticProperty('bar');
While the getStaticProperty()
method can be exposed publicly there is a problem that anything can essentially create a static property for a class. Even though this can not be prevented in PHP 4.x it is still a good idea to explicitly define known static properties. I find creating accessor methods for static properties to be the best way to achieve this. Here is an example:
class Foo extends Object {
function & getStaticBar() {
return Foo::getStaticProperty('bar');
}
function setStaticBar($var) {
$static_bar =& Foo::getStaticProperty('bar');
$static_bar = $var;
}
}
It is important to take a moment to note the limitation of these static properties. Because of the way they are retrieved by reference and stored into local properties it is not possible to assign a reference to these static properties. For example, the following code would not work as one might think:
$static_foo_bar =& Foo::getStaticProperty('bar');
$static_foo_bar =& new Foo();
Because the assignment from new Foo()
is by reference the property $static_foo_bar
is reassigned to a reference to a Foo
instance. This makes things like setting a static property to an instance of a Singleton impossible using this method. Here is an example of static properties being defined using accessor methods and inherited from the base Object
class:
class Object {
function & getStaticProperty($var) {
static $static_properties;
return $static_properties[$var];
}
}
class Foo extends Object {
function & getStaticBar() {
return Foo::getStaticProperty('bar');
}
function setStaticBar($var) {
$static_bar =& Foo::getStaticProperty('bar');
$static_bar = $var;
}
}
var_dump(Foo::getStaticBar());
Foo::setStaticBar(1);
var_dump(Foo::getStaticBar());
var_dump(Object::getStaticProperty('bar'));
Output:
NULL
int(1)
NULL
The above method works well but it has its limits. Here we will define static properties that can be assigned references. To do this we will change the getStaticProperty
method to optionally set by reference:
function & staticProperty($var_name, & $reference) {
static $static_properties;
if (isset($reference)) {
$static_properties[$var_name] =& $reference;
}
return $static_properties[$var_name];
}
Since our method changed we need to modify our accessor methods. A new accessor method is added to handle passing by reference:
function & getStaticBar() {
return Foo::staticProperty('bar', $_null);
}
function setStaticBar($var) {
Foo::staticProperty('bar', $var);
}
function setStaticBarRef(& $var) {
Foo::staticProperty('bar', $var);
}
Putting it all together we get:
class Object {
function & staticProperty($var_name, & $reference) {
static $static_properties;
if (isset($reference)) {
$static_properties[$var_name] =& $reference;
}
return $static_properties[$var_name];
}
}
class Foo extends Object {
function & getStaticBar() {
return Foo::staticProperty('bar', $_null);
}
function setStaticBar($var) {
Foo::staticProperty('bar', $var);
}
function setStaticBarRef(& $var) {
Foo::staticProperty('bar', $var);
}
}
$test = 1;
var_dump(Foo::getStaticBar());
Foo::setStaticBar($test);
var_dump(Foo::getStaticBar());
$test = 2;
var_dump(Foo::getStaticBar());
Foo::setStaticBarRef($test);
$test = 3;
var_dump(Foo::getStaticBar());
Output:
NULL
int(1)
int(1)
int(3)
With PHP 5 we instantly have access to static properties, as well as the ability to declare static methods explicitly. In fact, all of our problems are solved with proper design. Here is an example of a static variable with accessor methods:
class Foo {
protected static $bar;
public static function & getStaticBar() {
return self::$bar;
}
public static function setStaticBar($var) {
self::$bar = $var;
}
}
var_dump(Foo::getStaticBar());
Foo::setStaticBar(1);
var_dump(Foo::getStaticBar());
Output:
NULL
int(1)