Delicious Bookmark this on Delicious Share on Facebook SlashdotSlashdot It! Digg! Digg



PHP : Language Reference : Classes and Objects (PHP 5) : Static Keyword

Static Keyword

Declaring class members or methods as static makes them accessible without needing an instantiation of the class. A member declared as static can not be accessed with an instantiated class object (though a static method can).

For compatibility with PHP 4, if no visibility declaration is used, then the member or method will be treated as if it was declared as public.

Because static methods are callable without an instance of the object created, the pseudo variable $this is not available inside the method declared as static.

Static properties cannot be accessed through the object using the arrow operator ->.

Calling non-static methods statically generates an E_STRICT level warning.

As of PHP 5.3.0, it's possible to reference the class using a variable. Keywords like self, parent or static are not allowed in dynamic class references.

Example 10.15. Static member example

<?php
class Foo
{
   public static
$my_static = 'foo';

   public function
staticValue() {
       return
self::$my_static;
   }
}

class
Bar extends Foo
{
   public function
fooStatic() {
       return
parent::$my_static;
   }
}


print
Foo::$my_static . "\n";

$foo = new Foo();
print
$foo->staticValue() . "\n";
print
$foo->my_static . "\n";      // Undefined "Property" my_static

print $foo::$my_static . "\n";
$classname = 'Foo';
print
$classname::$my_static . "\n";

print
Bar::$my_static . "\n";
$bar = new Bar();
print
$bar->fooStatic() . "\n";
?>


Example 10.16. Static method example

<?php
class Foo {
   public static function
aStaticMethod() {
       
// ...
   
}
}

Foo::aStaticMethod();
$classname = 'Foo';
$classname::aStaticMethod();
?>


Code Examples / Notes » language.oop5.static

dmintz

[Editor's Note: This is done for back compatability. Depending on your error level, An E_STRICT error will be thrown.]
PHP 5.0.1 doesn't seem to mind if you call a static method in a non-static context, though it might not be the best of style to do so.
On the other hand, PHP complains if you try to try to call a non-static method in a static context (if your error reporting is cranked up to E_STRICT).
class Test {

   static function static_method() {
       echo "Here's your static method: Foo!<br />\n";
   }
   function static_method_caller() {
       echo "static_method_caller says:  ";$this->static_method();
   }
   function non_static() {
       echo "I am not a static method<br />\n";
   }
}
$t = new Test();
$t->static_method();
$t->static_method_caller();
Test::non_static();


06-apr-2005 11:14

You misunderstand the meaning of inheritance : there is no duplication of members when you inherit from a base class. Members are shared through inheritance, and can be accessed by derived classes according to visibility (public, protected, private).
The difference between static and non static members is only that a non static member is tied to an instance of a class although a static member is tied to the class, and not to a particular instance.
That is, a static member is shared by all instances of a class although a non static member exists for each instance of  class.
Thus, in your example, the static property has the correct value, according to principles of object oriented conception.
class Base
{
 public $a;
 public static $b;
}
class Derived extends Base
{
 public function __construct()
 {
   $this->a = 0;
   parent::$b = 0;
 }
 public function f()
 {
   $this->a++;
   parent::$b++;
 }
}
$i1 = new Derived;
$i2 = new Derived;
$i1->f();
echo $i1->a, ' ', Derived::$b, "\n";
$i2->f();
echo $i2->a, ' ', Derived::$b, "\n";
outputs
1 1
1 2


yarco dot w

Use a variable to initialize a static variable also trigger errors.
For example:
<?php
function test()
{
 $t = time();
 static $buf[] = $t; // this wouldn't work
}
?>
But you can do it seperatly:
<?php
function test()
{
 static $buf;
 $t = time();
 $buf[] = $t;
}
?>


aidan

To check if a function was called statically or not, you'll need to do:
<?php
function foo () {
   $isStatic = !(isset($this) && get_class($this) == __CLASS__);
}
?>
More at (http://blog.phpdoc.info/archives/4-Schizophrenic-Methods.html).
(I'll add this to the manual soon).


jan dot -re-mov.ethis-mazanek/at-abeo.cz

This reacts to comment from
michael at digitalgnosis dot removethis dot com from 16-Dec-2004 08:09
> Note that Base::Foo() may no longer be declared 'static' since static methods cannot be overridden (this means it will trigger errors if error level includes E_STRICT.)
In my test on Windows PHP Version 5.1.4 it seems that it *is possible* to override static method.
This code works at my machine without producing E_STRICT error:
<?php
class Base
{
  static function Foo ( $class = __CLASS__ )
  {
      call_user_func(array($class,'Bar'));
  }
}
class Derived extends Base
{
  static function Foo ( $class = __CLASS__ )
  {
      parent::Foo($class);
  }
  static function Bar ()
  {
      echo "Derived::Bar()";
  }
}
Derived::Foo(); // This time it works.
?>


clment genzmer

The best solution I found for the non-inherited static problem : pass the name of the class.
<?php
class A {
   
   public static $my_vars = "I'm in A";
   
   static function find($class) {
        $vars = get_class_vars($class) ;
        echo $vars['my_vars'] ;
   }
}
class B extends A {
    public static $my_vars = "I'm in B";
}
B::find("B");
// Result : "I'm in B"
?>


condor

Static methods (of course) may be abstract, and therefore you may define static methods in Interfaces:
<?php
interface Foo {
   static function doSomething($a);
}
class Bar implements Foo {
   public static function doSomething($a) {
       echo 'Hi!';
   }
}
?>
Leaving the implementation of doSomething() away will cause a Fatal Error.
(Just as a note 'cause I asked myself whether it would be possible :))


christian

STATIC is cool. Here is an example how to get an existing instance as a Singleton:
<?php
class Singleton {
private static $instance=null;
private $value=null;
private function __construct($value) {
$this->value = $value;
}
public static function getInstance() {
if ( self::$instance == null ) {
echo "
new
";
self::$instance = new Singleton("values");
}  else {
echo "
old
";
}
return self::$instance;
}
}
$x = Singleton::getInstance();
var_dump($x); // returns the new object
$y = Singleton::getInstance();
var_dump($y); // returns the existing object
?>
ckj


james

One way to get around the fact that static variables are shared throughout the inheritance tree to map a instance variable to a global variable named after the class.
<?php
$GLOBALS['static'] = array();
class root {
 public $self;
 public static $all_instances;
 
 function __construct() {
   $this->self = &$GLOBALS['static'][get_class($this)];
   $this->self['instances'] += 1;
   self::$all_instances     += 1;
 }
}
class child_a extends root {
}
class child_b extends root {
}
$a1 = new child_a();
$a2 = new child_a();
$a3 = new child_a();
$b1 = new child_b();
$b2 = new child_b();
echo "child_a instances: " . $a3->self['instances'] . " | all_instances: " . child_a::$all_instances . "\n";
echo "child_b instances: " . $b2->self['instances'] . " | all_instances: " . child_b::$all_instances . "\n";
echo "\$GLOBALS['static'] = ";
var_dump($GLOBALS['static']);
?>
// Output:
child_a instances: 3 | all_instances: 5
child_b instances: 2 | all_instances: 5
$GLOBALS['static'] = array(2) {
 ["child_a"]=>
 &array(1) {
   ["instances"]=>
   int(3)
 }
 ["child_b"]=>
 &array(1) {
   ["instances"]=>
   int(2)
 }
}


nospam dot dd

Not sure if this gets around the static inheritance problem, but it does seem to work:
<?php
// Declare the interface 'iDomainProperties'
interface iDomainProperties {
 static function property_setup();
}
// define superclass
class domainobject implements iDomainProperties {
 protected $properties;
 
 static function property_setup() { return array(); }
}
// define subclass
class person_object extends domainobject {
 
 static function property_setup() {
   $properties = array('type' => 'int', 'size' => '10');
   return $properties;
 }
}
// now ask for static function from person_object
print_r(person_object::property_setup());
?>
results in
Array
(
   [type] => int
   [size] => 10
)


daxxar

Just to point it out, this is slightly different from the C++ OO approach.
The following code compiles and runs fine using g++ with the options -W -Wall -pedantic :)
#include <iostream>
struct Foo { static void Bar() { std::cout << "Hi!" << std::endl; } };
int main() { Foo x; x.Bar(); return 0; }
Whereas accessing a static method via an instance of a class in PHP doesn't work.
It's not a problem, but it's perhaps worth noting, if you're used to C++ OO.


michalf

Inheritance with the static elements is a nightmare in php. Consider the following code:
<?php
class BaseClass{
public static $property;
}
class DerivedClassOne extends BaseClass{
}
class DerivedClassTwo extends BaseClass{
}
DerivedClassOne::$property = "foo";
DerivedClassTwo::$property = "bar";
echo DerivedClassOne::$property; //one would naively expect "foo"...
?>
What would you expect as an output? "foo"? wrong. It is "bar"!!! Static variables are not inherited, they point to the BaseClass::$property.
At this point I think it is a big pity inheritance does not work in case of static variables/methods. Keep this in mind and save your time when debugging.
best regards - michal


meszaros dot gergely

If you need a workaround for a static property overloading problem (see previous post) try this:
<?php
abstract class a {
   public static $lala = '1';
   function __construct () {
       # echo self::$lala
       $vars = get_class_vars(get_class($this));
       echo $vars['lala'];
   }
}
class b extends a {
    public static $lala = '2';
}
new b();
?>


michael

If you are trying to write classes that do this:
<?php
class Base
{
   static function Foo ()
   {
       self::Bar();
   }
}
class Derived extends Base
{
   function Bar ()
   {
       echo "Derived::Bar()";
   }
}
Derived::Foo(); // we want this to print "Derived::Bar()"
?>
Then you'll find that PHP can't (unless somebody knows the Right Way?) since 'self::' refers to the class which owns the /code/, not the actual class which is called at runtime. (__CLASS__ doesn't work either, because: A. it cannot appear before ::, and B. it behaves like 'self')
But if you must, then here's a (only slightly nasty) workaround:
<?php
class Base
{
   function Foo ( $class = __CLASS__ )
   {
       call_user_func(array($class,'Bar'));
   }
}
class Derived extends Base
{
   function Foo ( $class = __CLASS__ )
   {
       parent::Foo($class);
   }
   function Bar ()
   {
       echo "Derived::Bar()";
   }
}
Derived::Foo(); // This time it works.  
?>
Note that Base::Foo() may no longer be declared 'static' since static methods cannot be overridden (this means it will trigger errors if error level includes E_STRICT.)
If Foo() takes parameters then list them before $class=__CLASS__ and in most cases, you can just forget about that parameter throughout your code.
The major caveat is, of course, that you must override Foo() in every subclass and must always include the $class parameter when calling parent::Foo().


erikzoltan nospam

I was doing this in a more complex example (than previous note) and found that I had to place the initialization statement AFTER the class in a file where I was using the __autoload function.

michael

Here's another way to do the same thing (see my post below) without having to muck up your Foo() function's parameters in the Base and all Derived classes.
However, you cannot use static, and still must define Foo() in derived classes.  This way also performs slower and may not always work--but it DOES make for prettier code.
<?php
class Base
{
   function Foo ()
   {
       $call = debug_backtrace();
       call_user_func(array($call[1]['class'],'Bar'));
   }
}
class Derived extends Base
{
   function Foo () { parent::Foo(); }
   function Bar ()
   {
       echo "Derived::Bar()";
   }
}
Derived::Foo();
?>


jakob schwendner

Here is my solution to the static search method problem for data objects. I found the debug_trace version posted earlier quite clever, but a little too risky.
<?php
class Foo {
static function find($class) {
$obj = new $class();
return $obj;
}
}
class Bar extends Foo {
static function find() {
return parent::find(__CLASS__);
}
function print_hello() {
echo("hello");
}
}
Bar::find()->print_hello();
?>


daxxar

Heh. The last post, eh, is wrong.
I didn't test it in PHP.
I saw it as an aberration to C++ when I read it, which is why I commented on it. So, I guess I misread "A member or method declared with static can not be accessed with a variable that is an instance of the object and cannot be re-defined in an extending class." to mean that you can't call $foo->StaticFunc(), (and when I explained the issue in the #php-channel on EFNet, I was under the impression that others thought likewise), when I guess it means that you can't access $this *inside* StaticFunc(). I dunno.
If it's a language bug, it should be fix, if it's a documentation "bug" (most likely), the documentation should be worded more cleary (rephrased), IMO. :)


nospam dot dd

Doh!
Yes of course my last example works, but it doesn't actually solve the problem of self being assigned in the superclass for static functions!!! Idiot.
Yes, you can only do it by passing the name of the subclass. In case, like me you've been struggling with it for a while, here's one way to do it, using a separate 'instatiate' method to do the generic leg-work for __construct in the superclass, whilst using a stub __construct method in all the subclasses to ensure that the correct static method gets called,
<?php
class domainobject {
 protected $properties; //!< associative array of domainobject properties
 public function __construct($new_object_properties = null) {
   $classname = 'domainobject';
   $this->instantiate($classname);
 }
 protected function instantiate($classname) {
   $this->properties = call_user_func(array($classname,'property_setup'));
 }
 
 static function property_setup() {
   $properties['id'] = array('type' => 'int', 'size' => '10');
   return $properties;
 }
}
class person_object extends domainobject {
 public function __construct($new_object_properties = null) {
   $classname = 'person_object';
   $this->instantiate($classname);
 }
 static function property_setup() {
   $properties['forename'] = array('type' => 'text', 'size' => '10', 'validations' => 'required');
   $properties['surname']  = array('type' => 'text', 'size' => '10', 'validations' => 'required');
   return $properties;
 }
}
class phone_object extends domainobject {
 public function __construct($new_object_properties = null) {
   $classname = 'phone_object';
   $this->instantiate($classname);
 }
 static function property_setup() {
   $properties['phone_label']    = array('type' => 'text',    'size' => '10');
   $properties['number']         = array('type' => 'text',    'size' => '10');
   return $properties;
 }
}
print_r(new phone_object());
print_r(new person_object());
/* Result:
   phone_object Object (
    [properties:protected] => Array
        (
            [phone_label] => Array ( [type] => text, [size] => 10 ),
            [number]      => Array ( [type] => text, [size] => 10 )
        )
  person_object Object (
   [properties:protected] => Array
       (
           [forename] => Array ( [type] => text, [size] => 10, [validations] => required ),
           [surname]  => Array ( [type] => text, [size] => 10, [validations] => required )
       )
) */
?>


gabe

Currently, inheritance with static methods can be a difficult matter, mainly because the 'self' keyword refers the exact class in which the reference is present, much like __CLASS__.  Thus, in a case like the following:
<?php
class A {
static function foo () {
echo "A::foo()";
}

static function callFoo () {
self::foo();
}
}
class B extends A {
static function foo () {
echo "B::foo()";
}
}
B::callFoo();
?>
Will output 'A::foo()' instead of 'B::foo()'.  As of 5.2 and below, there is no clean way to get around this.  get_class(), self, __CLASS__, and even the stack (examined by debug_backtrace()) will all report the appropriate class as being 'A', which is resolved before being called.  There is no sane way, short of determining the filename and line of code from debug_backtrace, re-opening the file, and parsing that out yourself (this kludge is left as an exercise to only the most demented developer).  This setup makes it extremely difficult to develop an ORM like ActiveRecord in PHP.
You'll see some rather ugly solutions below, including passing the class name to callFoo().  Another possible route is to skip static calls all together and make a function that returns an instance of the object, thus allowing you to gain access to the '$this' variable (which *will* know the class name that was originally being called):
<?php
class A {
static function foo () {
echo "A::foo()";
}

static function callFoo () {
$this->foo();
}
}
class B extends A {
static function foo () {
echo "B::foo()";
}
}
function getB () { return new B(); }
getB()->callFoo();
?>
Luckily, a work around has been committed to PHP's HEAD, and should be available in the 5.3 series.  The concept is called "late static binding" (LSB), and can be read about at http://www.colder.ch/news/08-24-2007/28/late-static-bindings-expl.html .  Basically, you'd have the exact same setup in as in the first example, but instead of calling "self::foo()", you instead would call "static::foo()".


ference

Both static and const fields can be accessed with the :: operator. However, while a constant can't be changed, this is not true for static variables.
If you want to access an array using the :: operator you have to declare the array static, since you can't have a constant array. Beware:
<?php
class foo
{
 static $stuff = array('key1' => 1, 'key2' => 2);
}
class bar
{
 public function __construct()
 {
   var_dump(foo::$stuff);
 }
}
class bad
{
 public function __construct()
 {
   foo::$stuff = FALSE;
 }
}
new bar();    // prints array(2) { ["key1"]=> int(1) ["key2"]=> int(2) }
new bad();
new bar();    // prints bool(false)
?>
A safe implementation requires a little more effort:
<?php
class foo
{
 private static $stuff = array('key1' => 1, 'key2' => 2);
 public final static function getstuff()
 {
   return self::$stuff;
 }
}
class bar
{
 public function __construct()
 {
   var_dump(foo::getstuff());
 }
}
class bad
{
 public function __construct()
 {
   foo::$stuff = FALSE;
 }
}
new bar();    // prints array(2) { ["key1"]=> int(1) ["key2"]=> int(2) }
new bad();    // results in a fatal error
?>


c_daught_d

A twist on christian at koch dot net's Singleton example is setting/getting non-static member variables using self::$instance->varname within static method calls.
Within the modified Singleton class below, the member variable $value is set within the getInstance static method instead of the constructor.
Whether this is "pure" OPP, I don't know. But it does work, is worth mentioning, and could be usefull.
class Singleton
{
   private static $instance=null;
   private $value=null;
   private function __construct() {
   }
   public static function getInstance() {
       if ( self::$instance == null ) {
           echo "
new
";
           self::$instance = new Singleton("values");
           self::$instance->value = "values";
       }
       else {
           echo "
old
";
       }
       return self::$instance;
   }
}


admin

<?php
       abstract class a {
               public
                       static $lala = '1';
               function __construct () {
                       echo self::$lala;
               }
       }
       class b extends a {
               public
                       static $lala = '2';
       }
       new b();
?>
This one outputs `1`.


Change Language


Follow Navioo On Twitter
Introduction
The Basics
Autoloading Objects
Constructors and Destructors
Visibility
Scope Resolution Operator (::)
Static Keyword
Class Constants
Class Abstraction
Object Interfaces
Overloading
Object Iteration
Patterns
Magic Methods
Final Keyword
Object cloning
Comparing objects
Reflection
Type Hinting
Late Static Bindings
eXTReMe Tracker