Wednesday, April 17, 2013

Static Variables in PHP

1. Static variables should be declared as shown in the example below. Parse error would be raised if we assign an expressions to them.

<?php
function foo()
{
   static $i = 0;             // Valid
   static $j = $i + 10;       // Invalid as a expression is assigned
   static $j = loo($i + 10);  // Invalid as explained above
}

function loo($i)
{
  return $i * $i;
}
?>


2. Check the code below to see some more on static variables.

<?php
function foo()
{
   static $j = loo; 
   $j++;
   echo "<br>$j";
}
foo();
foo();
foo();
?>


Output :
Notice: Use of undefined constant loo - assumed 'loo' in C:\xampp\htdocs\test.php on line 4

lop
loq
lor

Note : the 'loo' is assumed to be a constant which was not defined earlier. Had it been defined before, the Notice would have gone away. Check the code below.

<?php
define("loo","A"); 
function foo()
{
   static $j = loo;  /// Constant can be assigned
   $j++;
   echo "<br>$j";
}
foo();
foo();
foo();
?>


Output :

B
C
D

Note : PHP characters behaved like integers in the code above; Actually the internal ASCII value is incremented/decremented like in C.

3. Inside a class, static variable can't be assigned with any constructor/function as shown in example below.

<?php
/// External Function
function foo()
{
  return 1;
}

//// Class Declaration
class One
{
    /// Initialize the static variable $var
    static $var = foo(); 

    /// Static function to retun static variable
    static function disp()
    {
       print ++ self::$var;
    }
}

One::disp();
One::disp();
One::disp();
?>


Output : An error message is shown.

Explanation : The statement static $var = foo(); is wrong, static variable can not be initialized with a function/constructor call. However the code can be written the following way to work properly.

<?php
/// External Function
function foo()
{
  return 1;
}

/// Static Variable Initialization, with 1 [returned by foo()]
One::$var = foo();

//// Class Declaration
class One
{
    /// Initialization of static variable is already done
    static $var; 

    /// Static function to return static variable
    static function disp()
    {
       print ++ self::$var;
    }
}

One::disp();  // Prints 2
One::disp();  // Prints 3
One::disp();  // Prints 4
?>


The code above is quite self-explanatory. We did an external initialization of static variable $var outside of the actual class definition. However this was possible because the static variable is was not declared as private. Check out the code below.

<?php
/// External Function
function foo()
{
  return 100;
}

class One
{
    ///// Private Static Member
    private static $var ;
   
    ///// Initialize Static Member against external functions
    static function init()
    {
      self::$var = foo();
    }
   
    /// Static function to retun static variable
    static function disp()
    {
        print ++ self::$var;
    }
}

One::init();  /// Initialize with 100
One::disp();  /// Prints 101
One::disp();  /// Prints 102
One::disp();  /// Prints 103
?>


Inheritance of static method is shown in the following example.

<?php
class one
{
    static protected $test = "class one";
    public static function static_test()
    {
       echo self::$test ;
    }
}

class two extends one
{
    //// This has to be static, otherwise re-declaration error occurs
    static protected $test = "class two";
}

two::static_test(); /// class one
?>


In this example, self:: is resolved using the class in which the method belongs. "this" can't be used inside a static method. The static_test() function does not exist in class two, but in class one. Hence "class one" is printed ... this is a limitation of self:: ... kind of "Early Binding" effect in C++. To get the effect of "Late Binding", we need to change the line

echo self::$test ;

to

echo static::$test ; /// This calls for Late Static Binding

As a result, "class two" is printed. But the construct "static::" can only be used with static properties. Another example where a different approach for accessing static properties is shown..


<?php
class Foo
{
   // Define static property

   public static $my_static = 1;
}
 

// Inheritance
class Bar extends Foo
{

}

// Parent Object

$foo = new Foo();
print $foo::$my_static; // 1
 

// Increment
$foo::$my_static ++;

// Child Object

$boo = new Bar();
print $boo::$my_static; // 2
?>


The program above access static properties using object. All the following constructs access the same static property..

echo Foo::$my_static;  // Class Name used
echo Bar::$my_static;  // Class Name used
echo $boo::$my_static; // Object used

Invoking static property of any abstract class is also possible.
<?php
abstract class Foo
{
    public static $bar = "100";
}
echo  ++Foo::$bar ; // prints 101

?>

No comments: