类与对象(PHP 4)
在线手册:中文  英文

范围解析操作符(::

Caution

下列内容仅在 PHP 4 及以后版本中有效。

有时,在没有声明任何实例的情况下访问类中的函数或者基类中的函数和变量很有用处。而 :: 运算符即用于此情况。

<?php
class {
    function 
example() {
        echo 
"I am the original function A::example().<br />\n";
    }
}

class 
extends {
    function 
example() {
        echo 
"I am the redefined function B::example().<br />\n";
        
A::example();
    }
}

// A 类没有对象,这将输出
//   I am the original function A::example().<br />
A::example();

// 建立一个 B 类的对象
$b = new B;

// 这将输出
//   I am the redefined function B::example().<br />
//   I am the original function A::example().<br />
$b->example();
?>

上面的例子调用了 A 类的函数 example(),但是这里并不存在 A 类的对象,因此不能这样用 $a->example() 或者类似的方法调用 example()。反而我们将 example() 作为一个类函数来调用,也就是说,作为一个类自身的函数来调用,而不是这个类的任何对象。

这里有类函数,但没有类的变量。实际上,在调用函数时完全没有任何对象。因而一个类的函数可以不使用任何对象(但可以使用局部或者全局变量),并且可以根本不使用 $this 变量。

上面的例子中,类 B 重新定义了函数 example()。A 类中原始定义的函数 example() 将被屏蔽并且不再生效,除非使用 :: 运算符来访问 A 类中的 example() 函数。如:A::example()(实际上,应该写为 parent::example(),下一章介绍该内容)。

就此而论,对于当前对象,它可能有对象变量。因此可以在对象函数的内部使用 $this 和对象变量。


类与对象(PHP 4)
在线手册:中文  英文

用户评论:

singh206 at gmail dot com (2008-07-22 11:12:13)

Using PHP 4, I was unable to see an easy method for retrieving static constants in a library, as well as static functions.  There was no need to set variables, as the library is final, used for Configuration settings.

<?php
class StaticLibrary
{
    
//static constants are set here
    
function finalConstants(&$Vars)
    {
        
$Vars['someVar']        = 'Hello';
        
$Vars['anotherVar']     = 'World';
        
$Vars['moreVars']       = 'Keep It Coming';
    }

    
//usage: StaticLibrary::vars('someVar')
    
function vars($v)
    {    
               static 
$Vars;
             if (!
is_array($Vars)) { $Vars = array(); StaticLibrary::finalConstants($Vars); } //setup access to the static contants in our Final library
             
return($Vars[$v]); //return some var
      
}

    
//usage: StaticLibrary::staticFunction('Some string and I want to ')    
    
function staticFunction($str)
    {
            
$str .= 'freak that string!';
            return 
$str;
    }
}
?>

  I appreciate the ideas below!!

philipp dot feigl at gmail dot com (2007-12-10 06:06:12)

As already pointed out in a previous comment, there is no way to statically access variables, i wrote this small workaround

<?php
class {
    var 
$MY_VIRTUAL_CONST 1;
    function 
MY_VIRTUAL_CONST() { $vars get_class_vars(__CLASS__); return $vars[strToUpper(__FUNCTION__)]; }
}

echo 
A::MY_VIRTUAL_CONST();
?>

This magically retrieves the correct value without creating an object instance and its easily copy & pasteable, as the methods content is completly generic.

Robert Chapin (2007-06-24 19:42:31)

I revised this example to give a better feel for the scope and overloading rules in PHP 4.

<?php
class {
    function 
example() {
        echo 
"I am the original function A::example().<br />\n";
        
$this->other();
    }
    function 
other() {
        echo 
"I am the original function A::other().<br />\n";
    }
}

class 
extends {
    function 
example() {
        echo 
"I am the redefined function B::example().<br />\n";
        
A::example();
    }
    function 
other() {
        echo 
"I am the redefined function B::other().<br />\n";
    }
}

// there is no object of class A.
// this will print
//   I am the original function A::example().<br />
//   PHP Fatal error:  Call to a member function on a non-object in test.php on line 5
A::example();

// create an object of class B.
$b = new B;

// this will print
//   I am the redefined function B::example().<br />
//   I am the original function A::example().<br />
//   I am the redefined function B::other().<br />
$b->example();
?> 

Robert Chapin
Chapin Information Services

deadimp at gmail dot com (2007-02-06 21:04:17)

I've noticed that you can't easily obtain a re-scoping of a function-to-object by external means, and it can only really be done by functions ["methods" to be proper] inside the class.
I dub this phenomon "inability to externally modifiy scope resolution of class method", 'cause I don't really know the technical name. (Maybe something else along the lines of "inability to combine scope resolution and member selector operators".)
Enough of this, on to the example:
<?php
class Base {
 var 
$a=5;
 function 
Func() {
  echo 
"Base::Func $this->a<br>";
 }
}
class 
Child extends Base {
 function 
Func() {
  
$this->a=35;
  
Base::Func();
  
//$this->Base::Func(); //Won't work either
  
echo "Child::Func $this->a<br>";
 }
}
$obj=new Child;
$obj->Func(); //That works, outputs as expected
$obj->Base::Func(); //ERROR - See below
?>
As for the error, I get the Hebrew "double colon", as Shachar Shemesh mentioned: "parse error, unexpected T_PAAMAYIM_NEKUDOTAYIM"
I find it odd that I can't do this, and using C++ (where you are able to do this), I feel restricted in this sense.
And I can't think of any workarounds right now, aside from using this scope resolution in the class scope.

NOTE: I'm using PHP 5.0.5 right now (used to be using 4.x, but might've switched it in xampp)

Ken Ismert -- kismert_at_gmail_dot_com (2006-09-14 18:31:05)

You can simulate the PHP 5 self keyword for static objects in PHP 4 by simply using the class name:

<?php
class {
    function 
static1() {
        return 
'1';
    }
    function 
static2() {
        
// equivalent to self::static1() in PHP 5
        
return A::static1() . ' and 2';
    }
}
// treat class A as static.
// this will print
//  1 and 2
A::static2();
?> 

The A:: reference works just as well internally as externally.

Shachar Shemesh (2006-09-09 00:41:57)

The PHP lexical analyzer gives this token the name "T_PAAMAYIM_NEKUDOTAYIM". It might as well have been written in Hebrew. Wait, it IS written in Hebrew. It means "double colon".
I'm writing this comment mostly so that people who are searching the web for what the #(!(@*&#$ errors such as "unexpected T_PAAMAYIM_NEKUDOTAYIM" or "missing T_PAAMAYIM_NEKUDOTAYIM" mean get to the right page in the PHP manual.
Shachar

docey (2006-07-28 11:38:36)

after doing some research as the manual was somewhat
vague, i found out that using $this in a class-function is
not fatal as the manual implied, its not even a warning.
it simply comes with a notice saying: $this is undefined.
it appears the class-function is just as a global function.
and as such the static keyword holds its value after scope
changes.
however it seems to also holds its value after the class
gets instanced. take a simple counter function thats a
member of a class. make a few calls to the counter to
let it count to lets say 3. then instance the class and let
it count it again 3 times. you think the score is now 3,
infact its 6.
so one simple way to find out if a function is called from
a instanced class or not is to have the constructor set a
class variable and then check for it using isset. since in
the class-function scope the $this is unavailable isset
will return false. but when the class has been instanced
it will return true.
btw, i tested it with php4.4.2CLI.
hope this will clear somethings up.

rudy at sandbenders dot ca (2005-11-14 10:20:40)

my last note is actually not 100% correct... as it is, trying to return a reference to an element of the class variables array won't work, even though the classVars function is declared as (possibly) returning a reference... the correct way to return a reference to one of your class variables would be

<?php

class theClass {
    ...
    function &
classVars($name NULL, ...) {
        static 
$myClassVars;
        ...
        
$myRef =& $myClassVars[$name];

        return(
$myRef);
    }
}

?>

which works as expected when you're looking for a reference. This should only be necessary when you're trying to return a reference to a piece of the array as opposed to the whole array itself. Simply doing this

<?php

return($myClassVars);

?>

works as expected, ie: you can get a reference to the whole array without needing to explicitly create a reference to it before returning.

rudy at sandbenders dot ca (2005-11-13 22:05:43)

Since re-posting a simplified version of the peterjoel.com solution to class variables in php4 was kinda lame, here's the modified solution to give you one function (per class) that allows you to use any number of 'class' variables...

<?php

class theClass {
    function &
classVars($name NULL$value NULL) {  // The classVars function is (possibly) returning a reference...
        
static $myClassVars;  // Define a static var to hold our 'class' vars...

        
if (!is_array($myClassVars)) {  // Initialize the array if it isn't already...
            
$myClassVars = array();
        }

        if (!
is_null($name) && !is_null($value)) {  // If we got two arguments, set the class var that was passed...
            
$myClassVars[$name] = $value;
        }

        if (!
is_null($name)) {  // If we got one argument, return the var it's referring to...
            
return($myClassVars[$name]);
        } else {
            return(
NULL);
        }
    }
}

// Setting class variables...

theClass::classVars("varOne""valueOne");
theClass::classVars("varTwo""valueTwo");

// Getting class variables...

$myRef = &theClass::classVars("varOne");
echo 
theClass::classVars("varTwo");

?>

You should be able to store anything in your class vars this way, and depending on how you call the function, you can have either a copy or a reference to the class var returned (see manual on 'returning by reference'...) Again, hope this helps someone...

rudy at sandbenders dot ca (2005-11-13 21:40:12)

'emulating' class variables in php4... peter at textstore dot c() dot il put me on the right track... I came up with the following and then before posting this realized that peterjoel.com has already posted almost the exact same thing... anyways, this is a little simpler and only involves one function instead of a getter/setter pair...
class myClass {
function &myVar($arg = NULL) {
static $myClassVar;
if (!is_null($arg)) {
$myClassVar = $arg;
}
return($myClassVar);
}
}
// Setting the 'class' var...
myClass::myVar($myNewClassVar);
// Getting the 'class' var...
$classVarRef = &myClass::myVar();
This should let you set up 'class' vars that will hold anything you can reference... with a little creative array usage, you could modify this to allow any number of class vars without having to write the same above function for each one... hope someone finds it useful...

JDS <jeff at newtnotes dot com> (2005-08-31 07:10:01)

Using an anonymous class instance via the scope resolution operator does not appear to call the constructor method of the class.  Thus, any "stuff" set up within a constructor method (the method called when creating a new instance of a class) will not get set up using anonymous classes.

So for example something like this

<?php
Class A{
    var 
$thing;
    function 
A(
        
$this->thing "hello";
    )
    function 
get ($var){
        return 
$this->$var;
    }
}

echo 
A::get('thing');
?>

will not print anything as A::thing does not get "set up" outside of the constructor.

You would have to create an instance of class A to get any value for A::thing.

For example:
<?php
$a 
= new A();
echo 
$a->get('thing');
?>
(prints "hello")

This is based on my observations and not from any official documentation.  I may be wrong about the details.

evert at collab dot nl (2005-08-28 13:21:50)

A note to RichardBronosky's suggestion:
This is a very insecure method, never unserialize user data because they might be able upload a totally different class.
They can only specify properties, not methods but if they can research your code they might be able to do uninteded stuff or create a XSS attack.
So only unserialize user-data when you are in a controlled safe enviroment.
Evert

RichardBronosky (firstname at lastname dot com) (2005-05-09 14:33:41)

In reply to tim dot ward at stivesdirect dot com:
I had a need to to do a very similar thing.  I wrote a class that will be used to create an object which can serialize itself into a cookie and be used to recover itself from the cookie later.  To do the recovery you must use the Scope Resolution Operator (::) to call a function as a class function (vs. and object function).  The recovery is very simple to initiate because there is only one line of code to call (e.g. $the_object = the_class::the_function(); )  But the function you call must do a ton of stuff, and call a few other functions within the class.  This is where the problem lies.

I would like to thank <brooke at jump dot net>, <pollita at php dot net>, and <MagicalTux at FF.ST> (from http://php.net/manual/en/function.get-class.php) for leading me to the solution.

<?php
class foo
{
   function 
get_object_from_cookie(...)
   {
      ...
      return 
unserialize($decrypted_cookie_data);
   }
   function 
recover_from_cookie()
   {  
      ...
prepare to recover...
      
// The next line is the tricky part.
      
$o call_user_func(array(__CLASS__'get_object_from_cookie'), $encryption_secret$cookie_name);
      
$temp $o->get_stuff();
      
$o->other_stuff $o->do_calculate($temp);
      
$o->do_complicated_things();
      return 
$o;
   }
}
$bar foo::recover_from_cookie();
...
?>

I hope that saves someone an hour.  It sure would have saved me one.

mark at branly dot com (2005-03-07 14:53:34)

I didn't see where this issue was addressed so in regards to this post:
\\-------\\//-------//
when using "::" operator inside class functions, you can achieve quite interesting results. let's take this example:
class cCat {
function Miew(){
// cCat does not have a member "kind", but cDog has, and we'll use it
echo "I am ".$this->kind.", and I say MIEW\n";

// here things are even stranger: does cCat class
// support WhoAmI function? guess again...
$this->WhoAmI();
}
}

class cDog {
var $kind = "DOG";
function Bark(){
// let's make this dog act like a cat:)
cCat::Miew();
}

function WhoAmI(){
echo "Yes, I'm really ".$this->kind."!";
}
}
$dog = new cDog();
echo $dog->Bark();
outputs:
I am DOG, and I say MIEW
Yes, I'm really DOG!
The interesting thing here is that cDog is not descendant of cCat nor vice versa, but cCat was able to use cDog member variable and function. When calling cCat::Miew() function, your $this variable is passed to that function, remaining cDog instance!
It looks like PHP doesn't check if some class is an ancestor of the class, calling function via '::'.
//------//\\--------\\
The problem here is not that PHP is not checking ancestry. The problem is that "$this" refers to the calling object $dog even though it is referenced inside the cCat class definition. Since a cCat is never instantiated, $this has not been scoped to it.
To further illustrate the point, if you never instatiate dog (or any object for that matter), $this will never be set and when you statically call the miew function, you will get the following output:
"I am , and I say MIEW"
This flexibility of member handling, PHP does not afford to methods and as such the second line of the miew function will generate a fatal error reporting that the method has been called from a non object.
If you did want to take it one step further in the whole ancestry guessing issue, try instatiating cCat and calling the miew function. You will get the same result as above *EXCEPT* the fatal error will inform you the function has not been defined.
So, there you have it--PHP DOES NOT guess at inheritance.

mark@thedarkside (2005-02-24 15:04:56)

Carrying on from the previous note, it is possible to call a member function statically using a variable for the name of the class, i.e.:

<?php
class MyObject {
   function 
myfunc() {
      return 
"Hello! ($this)";  // '$this' to determine whether it is being called statically
   
}
}

$type "MyObject";
$object = new $type();

$message $object->myfunc();
$message MyObject->myfunc();
$message call_user_func(array(&$type"myfunc"));

O.K., so it's not using the scope resolution operator, but it does what you want... it calls 'myfunc' statically from the class named by $type.

Tom Wiltshire (2005-02-24 04:33:29)

It's worth noting that you can't use a variable with this operator.
The following is legal:
class MyObject {
function myfunc() {
return "Hello!";
}
}
$type = "MyObject";
$object = new $type();
$message = $object->myfunc();
(Puts "hello" in $message)
You can also use the scope operator:
$message = MyObject::myfunc();
However, the following is NOT legal:
$message = $type::myfunc();
It's a pity, 'cos right now I've got a situation where it'd be really handy, but that's the way it goes!

stefano at obliquid dot it (2004-07-07 17:22:00)

peter has a good point to suggest the use of static function variables instead of static class variables that PHP 4 does not support.
Unfortunately, also the first sentence of the manual is misleading "... refer to functions and variables in base classes or to refer to functions in classes that have not yet any instances. The :: operator is being used for this.".
You cannot use the :: operator on class variables since there are no static class variables. I lost some time trying to refer to class variable with this operator, so I think it may be useful to post a warning.
http://dev.obliquid.com

tango23 at inbox dot lv (2004-05-06 07:20:02)

>> That's how to make class' static variable in PHP4.
Note, that nobody seems to have a way of actually making a global static server-wide object in PHP.
All the static/class var ways above work only within a single PHP page.
If you want to do something like:
class Logger
{
...
function Logger($filepath)
...
}
in some global include file:
$logobj = new Logger("mylogfile");
and then in all of your pages:
$logobj->log("my message");
and there is no way you can make this logobj static (such that all your pages can refer to without making unncecessary copies).
Can't be done with using uninstantiated Logger::log() funcs either, because you are not setting the logfile filepath parameter anywhere persistent.
The only kludge seems to be to use the filepath as a global variable and use Logger:: syntax.

altherac at yahoo dot fr (2004-03-14 14:28:36)

Using a class function is a good way to write a Singleton pattern in php 4 using a static variable.

The sample code below shows the pattern in action : 

<?
    class Singleton
    {
        var $_info = null;

        function Singleton() {
            $this->_info = 'Original value';
        }

        function getInfo() {
            return $this->_info;
        }

        function setInfo($info) {
            $this->_info = $info;
        }

        function &getInstance() {
            static $instance = null;

            if (is_null($instance)) {
                $instance = new Singleton();
            }
            return $instance;
        }
    }

    $a = & Singleton::getInstance();
    $b = & Singleton::getInstance();
    $a->setInfo('Hi, my name is A');
    echo $b->getInfo();

?>

I have seen some Singleton pattern implementations that were using an external function to instanciate the object, but I don't think it is the best way to implement the pattern.

You may want to force the getInstance() function to be called in a static way with the :: operator by testing if $this is set and raising an error or returning a null value (depending on your design).

Rami Kayyali (rami at bluecubex dot com) (2003-11-07 20:20:34)

Regarding the note by "gk at proliberty dot com". No, eval() isn't superior to call_user_func(), eval() has security issues and performance overhead.
To achieve the same results using your example with call_user_func, simply pass $this_class by reference. This is probably because call_user_func is passing a copy of $this_class.

<?php

function init(&$this_class$current_class$paramsNULL ){
    
$this_class->classFiles[] = __FILE__;

    
$parent_class=get_parent_class($current_class);
    if( !empty(
$parent_class)){
        
// call_user_func() NOW DOES CORRECTLY UPDATE $this_class->classFiles :)
        
call_user_func(array($parent_class,'init'),
        &
$this_class,$parent_class,$params);
    }
   
// init()

?>

But please note, call-time pass-by-reference has been deprecared, or at least, PHP 4.3.2 says so.

Conclusion: Minimize using eval as much as possible, many projects had major security issues because they were using eval().

brooke at jump dot net (2003-11-07 03:27:24)

Someone mentioned that eval was better than call_user_func because the latter would not result in updates to the objects. I'm not sure this is the right place for such a debate, but if it is, then the right way is:
call_user_func(array(&this, $method), $arg1, $arg2);
You put a reference to (instead of a copy of) this in the array which you pass on.

wikiz at studentas dot lt (2003-06-15 05:40:02)

when using "::" operator inside class functions, you can achieve quite interesting results. let's take this example:
class cCat {
function Miew(){
// cCat does not have a member "kind", but cDog has, and we'll use it
echo "I am ".$this->kind.", and I say MIEW\n";

// here things are even stranger: does cCat class
// support WhoAmI function? guess again...
$this->WhoAmI();
}
}

class cDog {
var $kind = "DOG";
function Bark(){
// let's make this dog act like a cat:)
cCat::Miew();
}

function WhoAmI(){
echo "Yes, I'm really ".$this->kind."!";
}
}
$dog = new cDog();
echo $dog->Bark();
outputs:
I am DOG, and I say MIEW
Yes, I'm really DOG!
The interesting thing here is that cDog is not descendant of cCat nor vice versa, but cCat was able to use cDog member variable and function. When calling cCat::Miew() function, your $this variable is passed to that function, remaining cDog instance!
It looks like PHP doesn't check if some class is an ancestor of the class, calling function via '::'.

gk at proliberty dot com (2003-05-28 18:33:23)

Contrary to the comment above, I have found that call_user_func() 
is inferior to eval() because call_user_func() does not correctly 
update objects passed by reference.

In the example below, each of my subclasses calls init(), passing 
a reference to the current object, whose class variables are 
initialized by classes in the hierarchy. The class variable 
$this->classFiles contains the paths of each file for classes in 
the hierarchy. It is not updated correctly using call_user_func() 
but eval() works fine.

<?php
///////////////////////////////////////////////////////
/*
  xobj( );
    constructor
    SUBCLASSES MUST NOT have any constructors 
*/
/////////////////////////////////////////////////////////
function xobj$paramsNULL ){ 

    
$current_class=get_class($this);
    
$this->init($this$current_class$params);
    
// $this->classFiles[0] is the file containing the final subclass
    
$this->classFile=$this->classFiles[0];
    
print_r($this->classFiles); exit;
    
$this->_init($params);
}

///////////////////////////////////////////////////////
/*
  void init(&$this_class, $current_class, $params= NULL );
    initialization
    this class MUST be overridden to set $this->classFiles correctly:
    initialization requires __FILE__ to get the path of every class file
*/
/////////////////////////////////////////////////////////
function init(&$this_class$current_class$paramsNULL ){ 
    
$this_class->classFiles[] = __FILE__;

    
$parent_class=get_parent_class($current_class);
    if( !empty(
$parent_class)){
        eval(
"$parent_class::init(\$this_class, \$parent_class, \$params);");
        
// call_user_func() DOES NOT CORRECTLY UPDATE $this_class->classFiles:
        //call_user_func(array($parent_class,'init'),
$this_class,$parent_class,$params);
    }
    
// init()

?>

RESULT, using eval():
Array
(
    [0] => /usr/local/apache/htdocs/common/php/xobj/xobj_subclass.php
    [1] => /usr/local/apache/htdocs/common/php/xobj/xobj.php
)

RESULT, using call_user_func():
Array
(
    [0] => /usr/local/apache/htdocs/common/php/xobj/xobj_subclass.php
)

pollita at php dot net (2002-12-28 19:47:30)

While the method described by robinv at ecosse dot net to call a method of an arbitrarily named function will work:
eval("$classname::$methodname(\$param1,\$param2);");
There is another way to do so without using eval():
call_user_func(array($classname,$methodname),$param1,$param2);
This will do the same thing without the performance hit of eval and without the added security concerns.

peterjoel.com (2002-11-17 20:12:59)

You can implement a getter/setter pair to emulate a class variable. The syntax isn't so weird:

<?

class A{
    function getVar($val=NULL){
        static $class_variable = 0;
        if($val != NULL){
            $class_variable = $val;
        }
        return $class_variable;
    }
    function setVar($val=0){
        return A::getVar($val);
    }
}

A::setVar(3);
print A::getVar();

?>

frederik at spam pandora dot be (2002-11-13 14:46:35)

My approach to using class constants is by making them functions.
Instead of
$var CONSTANT = 1;
I use
function CONSTANT { return 1; }
Now, when using this:
$i = ConstantClass::CONSTANT();
You can do anything with it: comparing, addition, multiplication. The syntax is a bit weird, but it works perfectly.

pierrick at hydromel_no_spam_ dot net (2002-09-24 11:39:12)

It's possible to access class member variables:
class Test {
var $vA = "hello world";
}
$class_var = get_class_vars(Test);
echo $class_var["vA"];
It's sound to be an ellegant way to acces them, no ? ;)

steven at caltech dot co dot uk (2002-08-28 06:50:48)

Re: jdominic@prodigy.net 08-Aug-2002 05:49
While it would be nice to have static instance variables you can simply create a method with the same name which returns the value you require. This means you don't have to instantiate an object when you only need its static content. For example:
class Colour {
function default () { return "black"; }
}
var $backgroundColour = Colour::default ();

jdominic at prodigy dot net (2002-08-08 12:49:27)

According to the documentation, there is no way to have a class variable, only class functions. There should be class variables, because there's no way to implement CONSTANTS. Something like this won't work:

<?
        class Employee {

        var $ACTIVE_EMPLOYEE = 1;

        //etc..
        }

        echo Employee::ACTIVE_EMPLOYEE;

        //Also tryed:

        echo Employee::$ACTIVE_EMPLOYEE

?>

returns:
Parse error: parse error, unexpected ';', expecting '(' in /home/x/public_html/Test.php on line 9

It forces you to create an instance of the class:

$emp = new Employee();
echo $emp->ACTIVE_EMPLOYEE;

carl at thep.lu.se (2002-03-13 09:20:21)

Note that if you have two classes, 'foo' and 'bar', and a function in foo called with $instance_of_foo->func() calls bar::func2(), $this will be defined in func2, and it will point at an object of class foo. In fact, you can redefine $this to point to an object of any class before calling bar::func2() to have $this to be a reference to that object. This means that you can't have functions that can be called either as static (::) or member(->), since you won't be able to tell the difference. This is a quite unfortunate consequence of the combination of references not containing any type information and it not being possible to call an explicitly chosen base class member function (that is, if x extends y there's no clean way to call y::f() on an object of class x (The unclean way is to assign $this to $instance_of_x, call y::f(), and reset $this to its old value.)).

peter at textstore dot c() dot il (2001-07-29 04:38:03)

And now, encapsulated in constructor. Isn't it nice? Ye, and it WILL work when   more objects of class are serialized & unserialized ONLY when serialized in array / hash by one serialize() call - as serialize() should be used. However, when unserialized, it doesn't affect actual instances' "static" variable - thus, there will be 2 or more static variables after unserialization... but you can still change __wakeup() and to access "real"(actual) class' static value's reference, thus you have to use special function for every static value, as in example above... Ye, PHP is good!@

<?
  class O {

    function O() {
        static $statValue=0;
        $this->statValue= &$statValue;
    }
  }

  $o1= &new O;
  $o2= &new O;

  echo "\$o1: ".$o1->statValue."<br>";
  echo "\$o2: ".$o2->statValue."<br>";

  $o1->statValue= 5;
  $o2->statValue= 10;

  echo "\$o1: ".$o1->statValue."<br>";
  echo "\$o2: ".$o2->statValue."<br>";
?>

peter at textstore dot c() dot il (2001-07-29 04:10:24)

That's how to make class' static variable in PHP4. That means reference returned by function value() is the same for all instances of class O, thus they can share common data. This reference is common just for instances on same PHP page, of course.

<?  class O {
    function &value() {
     static $val=0;
     return $val;
    }
  }

  $o1= &new O;
  $o2= &new O;

  echo "\$o1: ".$o1->value()."<b"."r>";
  echo "\$o2: ".$o2->value()."<b"."r>";

  $ref1= &$o1->value();
  $ref1= 5;

  $ref2= &$o2->value();
  $ref2= 10;

  echo "\$o1: ".$o1->value()."<b"."r>";
  echo "\$o2: ".$o2->value()."<b"."r>";
?>

易百教程