章 18. 类与对象(PHP 4)

类是变量与作用于这些变量的函数的集合。使用下面的语法定义一个类:

<?php
class Cart {
    var
$items;  // 购物车中的物品

    // 将 $num 个 $artnr 物品加入购物车

    
function add_item($artnr, $num) {
        
$this->items[$artnr] += $num;
    }

    
// 将 $num 个 $artnr 物品从购物车中取出

    
function remove_item($artnr, $num) {
        if (
$this->items[$artnr] > $num) {
            
$this->items[$artnr] -= $num;
            return
true;
        } elseif (
$this->items[$artnr] == $num) {
            unset(
$this->items[$artnr]);
            return
true;
        } else {
            return
false;
        }
    }
}
?>

上面的例子定义了一个 Cart 类,这个类由购物车中的商品构成的数组和两个用于从购物车中添加和删除商品的函数组成。

警告

不能将一个类的定义分割到多个文件中。也不能将一个类的定义分割到多个 PHP 块中,除非该分割是在一个方法声明内部。以下用法将不起作用:

<?php
class test {
?>
<?php
    
function test() {
        print
'OK';
    }
}
?>

但是以下用法是可以的:

<?php
class test {
    function
test() {
        
?>
        <?php
        
print 'OK';
    }
}
?>

以下警告仅用于 PHP 4。

注意

名称 stdClass 已经被 Zend 使用并保留。不能在 PHP 代码中定义名为 stdClass 的类。

注意

函数名 __sleep__wakeup 在 PHP 类中是魔术函数。除非想要与之联系的魔术功能,否则在任何类中都不能以此命名函数。

注意

PHP 将所有以 __ 开头的函数名保留为魔术函数。除非想要使用一些见于文档中的魔术功能,否则建议不要在 PHP 中将函数名以 __ 开头。

在 PHP 4 中,var 变量的值只能初始化为常量。用非常量值初始化变量,需要一个初始化函数,该函数在对象被创建时自动被调用。这样一个函数被称之为构造函数(见下面)。

<?php
/* PHP 4 中不能这样用 */
class Cart {
    var
$todays_date = date("Y-m-d");
    var
$name = $firstname;
    var
$owner = 'Fred ' . 'Jones';
    
/* 不过包含有常量的数组可以 */
    
var $items = array("VCR", "TV");
}

/* 应该这样进行 */
class Cart {
    var
$todays_date;
    var
$name;
    var
$owner;
    var
$items = array("VCR", "TV");
    function
Cart() {
        
$this->todays_date = date("Y-m-d");
        
$this->name = $GLOBALS['firstname'];
        
/* etc. . . */
    
}
}
?>

类也是一种类型,就是说,它们是实际变量的蓝图。必须用 new 运算符来创建相应类型的变量。

<?php
$cart
= new Cart;
$cart->add_item("10", 1);

$another_cart = new Cart;
$another_cart->add_item("0815", 3);
?>

上述代码创建了两个 Cart 类的对象 $cart$another_cart,对象 $cart 的方法 add_item() 被调用时,添加了 1 件 10 号商品。对于对象 $another_cart,3 件 0815 号商品被添加到购物车中。

$cart$another_cart 都有方法 add_item(),remove_item() 和一个 items 变量。它们都是明显的函数和变量。可以把它们当作文件系统中的某些类似目录的东西来考虑。在文件系统中,可以拥有两个不同的 README.TXT 文件,只要不在相同的目录中。正如从为了根目录访问每个文件需要输入该文件的完整的路径名一样,必须指定需要调用的函数的完整名称:在 PHP 术语中,根目录将是全局名字空间,路径名符号将是 ->。因而,名称 $cart->items$another_cart->items 命名了两个不同的变量。注意变量名为 $cart->items,不是 $cart->$items,那是因为在 PHP 中一个变量名只有一个单独的美元符号。

<?php
// 正确,只有一个 $
$cart->items = array("10" => 1);

// 不正确,因为 $cart->$items 变成了 $cart->""
$cart->$items = array("10" => 1);

// 正确,但可能不是想要的结果:
// $cart->$myvar 变成了 $cart->items
$myvar = 'items';
$cart->$myvar = array("10" => 1);
?>

在定义类的时候,无法得知将使什么名字的对象来访问:在编写 Cart 类时,并不知道之后对象的名称将会命名为 $cart 或者 $another_cart。因而你不能在类中使用 $cart->items。然而为了类定义的内部访问自身的函数和变量,可以使用伪变量 $this 来达到这个目的。$this 变量可以理解为“我自己的”或者“当前对象”。因而 '$this->items[$artnr] += $num' 可以理解为“我自己的物品数组的 $artnr 计数器加 $num”或者“在当前对象的物品数组的 $artnr 计数器加 $num”。

注: 伪变量 $this 通常未定义,如果其所在的方法是被静态调用的话。但这不是个严格规定:如果一个方法被从另一个对象内静态调用的话,则 $this 会被定义。此时 $this 的值是那个发出调用的对象。用下例演示:

<?php
class A
{
    function
foo()
    {
        if (isset(
$this)) {
            echo
'$this is defined (';
            echo
get_class($this);
            echo
")\n";
        } else {
            echo
"\$this is not defined.\n";
        }
    }
}

class
B
{
    function
bar()
    {
        
A::foo();
    }
}

$a = new A();
$a->foo();
A::foo();
$b = new B();
$b->bar();
B::bar();
?>

上例将输出:

$this is defined (a)
$this is not defined.
$this is defined (b)
$this is not defined.

注: 有一些不错的函数用来处理类和对象。应该关注一下类/对象函数


add a note add a note User Contributed Notes
chris at simplekiosks dot com
14-Apr-2006 12:31
I took the above examples and extented them slightly to also allow you to run any function in the subclass without having to first declare it in the main class.

Enjoy

<?php

class mainClass
{
  
/*
   * Class loading function.
   *
   *
   *
   *
   */

      
var $module;

       function
LoadClass($loadModule)
       {
            
$this->module = new $loadModule; // this is much better
      
}

       function
RunFunction($FunctionName)
       {
          
$this->module->$FunctionName();       
       }

       function
ListFunctions()
       {

       }

    
// function out()
     //{
     //    $this->module->out();
     // }
}

class
subclass
{
   function
out()
   {
       echo
"Worked";
   }

   function
NewFunction()
   {
       echo
"<br>Good Lord<br>";
   }

   function
ThirdFunction()
   {
       echo
"<br>eh....<br>";

   }
}

echo
"Start of class manulapations<br>";
//$loadModule = new subclass;
$mainclass=new mainClass;
$mainclass->LoadClass("subclass");
//$mainclass->out();
$mainclass->RunFunction('NewFunction');
//$mainclass->ThirdFunction();
echo "End of class manulapation<br>";
?>
Leonel Quinteros
09-Feb-2006 10:57
PHP Allow to extend a class in a dinamic way into a object and only affects that object not the others of the same class.

I was developing a persistence class and i found this:

<?php
class MyClass {
   var
$Prop1;
  
  
// Into the constructor i create a propertie that was not declared before.
  
function MyClass() {
      
$this->Prop2 = "This was not declared but now exists into the object";
   }

   function
setProp($PropName, $PropValue) {
      
$this->$PropName = $PropValue;
   }
}

$MyObj = new MyClass();
$MyObj->setProp("Prop1", "This was declared and now has value");
$MyObj->setProp("Prop3", "This was declared by setProp() method.");
$MyObj->Prop4 = "This was declared out of the class definition";

echo
"Prop1: ".$MyObj->Prop1." <br />\r\n";
echo
"Prop2: ".$MyObj->Prop2." <br />\r\n";
echo
"Prop3: ".$MyObj->Prop3." <br />\r\n";
echo
"Prop4: ".$MyObj->Prop4." <br />\r\n";

?>

This could be very useful, but very dangerous too, take care.
Wolverine
02-Feb-2006 01:30
In case you would like to interrupt object construction on some condition and return false for further checking:

<?php
class Foo
{
    
// Constructor
    
function Foo()
     {
          
/*  Some inits here */

          
$someval=false;

           if (
$someval===false)
           {
               return
false;
           }
     }
}

$obj=new Foo();    // This won't work and will return partially initialised object instead of false

class Bar
{
    
// Constructor
    
function Bar()
     {
          
/*  Some inits here */

          
$someval=false;

           if (
$someval===false)
           {
              
$this=false;
               return;
           }
     }
}

$obj2=new Bar();    // This will work as expected and return false
?>

Hope this helps some people.
Karim Ahmed
21-Oct-2005 03:46
This class method allows you to take a nice associative array of parameters into your class when the number of parameters gets unmanagable and/or has lots of default-value parameters.

It is so useful I suggest putting on a general base class (I call mine Object) so all your descendents can use it.

-----------------------------------------------------

Code:

-----------------------------------------------------

   function setClassVars( &$parameter_array )
   {
       $class            = get_class($this);
       $class_vars = get_class_vars($class);
       /*
       * check that each of the passed parameters are valid before setting the
       * appropriate class variable.
       */
       foreach ( $parameter_array as $var => $value ){
           if ( array_key_exists( $var, $class_vars ) ){       
               $this->$var = $value;
           }
           else{
               $this->raiseError(
                   'setClassVars: class variable "' .
                   $var .
                   '" does not exist on class "' .
                   $class . '"'
               );
           }
       }
   }
-----------------------------------------------------

for example:

A complicated, messy, class method Before:

-----------------------------------------------------
 render(
  &$business_object,
  $on_change=false,
  $on_blur=false,
  $options=false
  $name
 ){
   $this->business_object = $business_object;
   $this->name = $name;
   $this->on_blur = $on_blur;
   $this->options = $options;
   <code>
}
-----------------------------------------------------

A nice clean method After:

-----------------------------------------------------
 render(
  &$parameter_array
 ){
   $this->setClassVars($parameter_array);
   <code>
}
-----------------------------------------------------

Example call:

-----------------------------------------------------
$parameter_array =
 array(

  'business_object' => $business_object,
  'name' => $field_name,
  'on_change' => 'form.submit()',
  'on_blur' => 'javascript:validate()',

  $options =>
   array(
     '1' => 'None Selected',
     '2' => 'Blue',
     '3' => 'Red'

   )
 );

$my_object->render( &$parameters );
-----------------------------------------------------

Now isn't that easier to read AND maintain. Now you can change your API without the hassle of amending every call to the method! You no longer have to worry about where the default params are or even the order of your params.

I hope someone else who has been swearing at their code finds this useful ;-)
GamblerZG
14-Oct-2005 10:27
To pascal dot poncet at netconsult dot com:

That's why MySQL has aliases. You can simply do this:
<?php
mysql_query
("SELECT found_rows() AS found_rows");
?>
pascal dot poncet at netconsult dot com
13-Oct-2005 10:22
Subject: using "sql_calc_found_rows" in a MySQL query while exploiting result in a PHP db class object.

Hello,

There is a nice function in MySQL that allows to know how many records would have been returned if no "where" clause were set : SQL_CALC_FOUND_ROWS.

If you have create a db object to collect the returned lines, you will be a little perplex when trying to call the result of this function.

Why ?
Simply because the returned field's name is "found_rows()" and obviously it's not possible to call something like :

<?php $result->found_rows() ?>

...as it will try to acces a method, not a property !

Then, the only way to get the right result seems to be the use of a class function, like :

<?php
  $db
->query("select found_rows()");
 
$count=current(get_object_vars(current($db->result)));
?>

Of course, if somebody found an other way to solve it, like a special syntax (see the one used with curled arrays in a string), I'm really open to discuss.

Good luck,
Pascal
Felix M dot Palmen <fmp at palmen dot homeip dot net>
11-Oct-2005 04:18
My way to implement a singleton in PHP4. I think it's the most convenient one since it works transparently using the constructor. Thanks to S.Radovanovic for his idea with referencing the class' variables, posted on http://www.php.net/manual/en/language.variables.scope.php

<?php

/* Singleton. Every instatiation returns the "same" object.
 *
 * for this to work, ALWAYS create objects with $object =& new class().
 * The reference operator doesn't do any harm in general and is
 * necessary for singletons.
 *
 * You also need to declare all the class' variables with "var" for
 * a singleton subclass. But that should always be a rule of good
 * design :)
 *
 * call parent::singleton() first in your subclass constructor.
 *
 * Of course, the subclass constructor should check if the object is already
 * initialized before doing any initialization.
 */

class singleton
{

  function
singleton()
  {
  
// static associative array containing the real objects, key is classname
  
static $instances=array();

  
// get classname
  
$class = get_class($this);

   if (!
array_key_exists($class, $instances))
   {
    
// does not yet exist, save in array
    
$instances[$class] = $this;
   }

  
// PHP doesn't allow us to assign a reference to $this, so we do this
   // little trick and fill our new object with references to the original
   // class' variables:
  
foreach (get_class_vars($class) as $var => $value)
   {
    
$this->$var =& $instances[$class]->$var;
   }
  }

}

?>
dave at davidhbrown dot us
04-Oct-2005 12:10
It appears that one must use eval if calling a static function  where the name of the class is in a variable:

     echo $class::staticfunc();

gets you a "parse error, unexpected T_PAAMAYIM_NEKUDOTAYIM" (in PHP 4.4.0)

while
   echo eval("return $class::staticfunc();");

behaves as desired.

Contrast this limitation with `->`which will accept a variable on both sides -- e.g., $myClass->$myFunc() -- and, of course, new $myClass is perfectly happy. The expression myClass::$myFunc() also works.
ia [AT] zoznam [DOT] sk
28-Sep-2005 05:45
to Menno Vanderlist:
And why bother to use eval?

<?php
class mainClass
{ //mainClass
      
var $module;

       function
mainClass($loadModule)
       {
// load modules
               //eval("\$this->module = new $loadModule;");

              
$this->module = new $loadModule; // this is much better
      
}

       function
out()
       {
//print out of loaded module
              
$this->module->out();
       }
}
?>

Functionality is the same, without the overhead when using eval().
Menno Vanderlist
30-Jul-2005 12:31
Using the extends statement with classes works, but it did the reverse of what I wanted. I want a modules hiearchy that adds a module into the main module. So I tried the following, after not finding anyone else who has done it, and it worked :)

<?php

class subClassA
{ //subClassA
      
function out()
       {
//subClassA::outA()
              
echo "testing subClassA\n";
       }
}

class
subClassB
{ //subClassB
      
function out()
       {
//subClassB::outB()
              
echo "testing subClassB\n";
       }
}

class
mainClass
{ //mainClass
      
var $module;

       function
mainClass($loadModule)
       {
// load modules
              
eval("\$this->module = new $loadModule;");
       }

       function
out()
       {
//print out of loaded module
              
$this->module->out();
       }
}

$mainA=new mainClass('subClassA');
$mainA->out();
$mainB=new mainClass('subClassB');
$mainB->out();
?>

outputs:
testing subClassA
testing subClassB
Niels Jaeckel
25-Apr-2005 04:37
My problem was, to write a class-method, that destroyes the class itself. After many hours I found the (assured) only possibility to implement this:

class A {

   function A() {

   }

   function DESTROY() {

     // this would not work:
     // unset($this);

     // but this:
     settype(&$this, 'null');

   }

}

This test-code worked on PHP 4.3.1:

$objA = new A();
var_dump($objA);        // Object...

$objA -> DESTROY();
var_dump($objA);        // NULL !!!

hth,
Niels
alberto dot delatorre at gmail dot com
12-Feb-2005 07:11
If you have a class hierarchy as this:

<?php
   abstract
class A{
      
//construct ommited
      
public function load(){
          
$this->_load();
       }

      
protected abstract function _load();
   }
  
   class
B extends A{
      
protected function _load(){
           echo
"loaded";
       }
   }
  
  
$b = new B();
  
$b->load();
?>

you encountered that you will have a 'calling an abstract method' in the line with '$this->_load'. To avoid this, just make another reference to $this and then call the method you'd want, this way:

<?php
   abstract
class A{
      
//construct ommited
      
public function load(){
          
$aux_this=&$this;
          
$aux_this->_load();
       }

      
protected abstract function _load();
   }
  
   class
B extends A{
      
protected function _load(){
           echo
"loaded";
       }
   }
  
  
$b = new B();
  
$b->load();
?>
arjini at gmail dot com
05-Feb-2005 05:56
Didn't see this anywhere obvious, so I'm posting it here. To access a memeber of an array with another variable you use $arr[$name]

To access a class method or property, you use $obj->{$name} You can also use the return value of a function.

<?php
  
class Test {
       function
methodName(){
           echo
'works!';
       }   
   }
  
   function
getName(){
       return
'methodName';
   }   
  
  
$t = new Test();
  
$t->{getName()}();

//works!
?>
spam at modem-help dot com
24-Jan-2005 01:32
Although the php 4.2.2 parser and variable storage are case-sensitive, classes + class-function + function declaration *storage* are not.

To example this, consider the following:

[note: constructor is `sendfile()', not `SendFile()' nor `sendFile()']
<?php
  
class SendFile {
  
// variables declared here

    
function SendFile() {
    
// function defined here
    
}

     function
sendFile() {
    
// function defined here
    
}

     function
sendfile() {
    
// function defined here
    
}

   }
// end class SendFile
?>

This was eventually illuminated by:

<?php
   print_r
( get_declared_classes());
?>

...in which a snippet of the result is:

Array
(
   [0] => stdClass
   [1] => __PHP_Incomplete_Class
   [2] => Directory
   [3] => DomNode
   [4] => DomDocument
   [5] => DomParser
...
   [24] => sendfile
)

Specifically, it appears that php has used initial-caps for all of it`s own (internal) classes, but that all user-classes are stored lower-cased, as are class + ordinary functions.

Written in the hope of saving someone else time & grief from this interesting `feature'.
rdc_uk
23-Jan-2005 12:44
Just found this interesting "gotcha";

If you implement a class with no member variables, calling the constructor does NOT produce an object. This can be a source of (great) consternation when producing classes which need no data storage.

Essentially if your class has no data members, all its methods are ONLY available statically, this can be a pain if defining object hierarchies with abstract base classes...

Example:

class A
{
  function A()
  {
     $i = 0; // not an empty constructor!
  }

  function fn()
  {
   return "A";
  }
}

$obj_a = new A();

$obj_a == null
$obj_a->fn(); will generate an error
A::fn(); works

Simply putting a "var $status=0;" in the class suddenly makes your object instantiatable.

This is certainly a "quirk" in an OO implementation, possibly a bug, definitely worth watching out for...
php dot net at mechintosh dot com
06-Dec-2004 07:52
While it is possible to use the names of existing PHP functions for class method names (not that you *should*, however sometimes there's really only one good name for a method even if it's taken..), you cannot use the names of language constructs like list(), echo, print etc, and appearantly also not of eval().

But you probably shouldn't be using PHP functionnames anyway :-)
email at richardlee dot info
06-Sep-2004 01:11
An example of how to pass an object back into its own class for direct use.

(thisClass.php)

<?php

class thisClass{

   var
$var1;
  
   function
thisClass($value)
       {
$this->var1 = $value;}
      
   function
set_var1($value)
       {
$this->var1 = $value;}
   function
get_var1()
       {return
$this->var1;}
  
   function
showVar()       
       {echo
"<p>var1 = ".$this->var1."</p>";}
  
   function
callShowVar($object)
       {
$object->showVar();}
  
   function
copyObject($object)
       {
$this->var1 = $object->get_var1();}

}

?>

(test.php)
<?php

require_once('class.php');

$thisObject = new thisClass(3);
$thatObject = new thisClass(1);

$thatObject->callShowVar($thisObject); //outputs "var1 = 3"

$thisObject->showVar(); //outputs "var1 = 3"
$thatObject->showVar(); //outputs "var1 = 1"
$thatObject->copyObject($thisObject);
$thatObject->showVar(); //outputs "var1 = 3"

?>
babs at sntteam dot org
31-Aug-2004 10:22
We can't split the class declaration in multiple PHP section but we can exit php tag in a function . ex :

<?
class plop {
   function
plop() {
      
$this->whatever = "bar";
   }
   function
foo() {
      
?>
        <pre>foo returns <?=$this->whatever?></pre>
       <?
  
}
};
$a = new plop;
$a->foo();
?>
will print : foo returns bar

PHP Version 4.3.8-9
bishop
20-Jul-2004 09:04
Say you have a factory method that needs to put data into an object before the constructor is called. This might be necessary, for example, if the factory class establishes a connection to a database and the manufactured object uses that connection in the constructor.

Do something like this:
<?php

function &factory($class /* ... */) {
 
// 1) get an object shell
 
$obj = new stdClass();

 
// 2) "type cast" it to the desired class
 
$tmp = explode(':', serialize($obj));
 
$tmp[1] = strlen($class);
 
$tmp[2] = '"' . $class . '"';
 
$obj = unserialize(implode(':', $tmp));

 
// 3) copy construct the manufacturer into the manufacturee
 
$obj->copyFrom($this);

 
// 4) call the real constructor
 
$args = func_get_args();
 
array_shift($args); // skip the class
 
call_user_func_array(array (&$obj, $class), $args);

  return
$obj;
}

?>

NOTE: The Editor's note in the "simon dot li at hongkong dot com" entry is misleading; it only works because the class names "foo" and "bar" are the same length. In general, you must change the first and second entries in serialized array as done above.

Also NOTE: This typecasting business works if you have a function that takes an arbitrary number of arguments and you want to pass those arbitrary arguments into a constructed class.  You can't just use call_user_func_array() in that case because 'new' is an operator, not a function.
catalin dot ivan at utoronto dot ca
07-Jul-2004 06:50
Regarding defining class variables:

The 'var' statement can NOT take Heredoc definitions, i.e. the "<<<MARKER" stuff (these may be somehow 'dynamic' as per warning above).

You must assign them values within the class constructor if you must use Heredoc.
oran at anonimous dot biu dot ac dot il
17-Jun-2003 01:34
class baseclass {
   function static1() {return "bla";}
   function static2() {return call_user_func(array(__CLASS__,'static1'));}
}

[ Editor's Note: Using the above, rather than below, will allow the static function to call its own generation's version of the method. ]

Unfortunately, inheritance of static methods is a bit problematic in PHP, because in order to use a static method you have to know the exact class it's defined in. This means trouble if you want to use one static function (or a static variable) from within another static function. For example:

class baseclass {
   function static1() {return "bla";}
   function static2() {return baseclass::static1();}
}

Now suppose that you write a class newclass that extends baseclass and redefines static1() to return "foo" instead of "bla" - this change will not be reflected in static2() of newclass. Not good at all.

You could use $this->static1() instead of baseclass::static1() in the definition of static2(), but then static2() will not be a static method. Another idea is to use get_class_name() to get the class name inside static2(), but again you need the $this variable to make this function call.

I found no way to overcome this problem, except to use real functions (not methods) for the purpose of wrapping my static functions. The name of the exact class to use is passed as a parameter to the wrapping function. It looks like this:

function wrapped_static1($clname) {
  if (in_array('static1', get_class_methods($clname)))
   return $clname::static1();
  return baseclass::static1();
}
function wrapped_static2($clname) {
  if (in_array('static2', get_class_methods($clname)))
   return $clname::static2();
  return baseclass::static2();
}

class baseclass {
   function static1() {return "bla";}
   function static2() {return wrapped_static1('baseclass');}
}

Now you can go on using baseclass and writing extension classes for it, using the following rules:
1. Use inheritance with your static functions in the natural way, as you would in C++. The wrapping code given here supports just 1 level of inheritance, but it may be improved to work its way up the inheritance tree using PHP's class functions.
2. When calling a static function, always call it through its wrapper.

For example:

class newclass extends baseclass    // example for rule 1
{
  function static1() {return 'foo';}
}
print static2_wrapper('newclass');  // example for rule 2

This is a little cumbersome, but now when you redefine a static function, you can be sure that any functions that rely on it will be able to use the correct definition.
russ dot taylor at nifty dot com
18-Apr-2003 04:31
It is sometimes useful to register a class instance as a session variable.  This can allow classes and their contained values to persist across multiple pages and/or frames.  Frames which need to use the registered class must be loaded (or reloaded) after the class instance is registered and the class declaration must be included in each file that needs to access the registered class.

i.e.
<?
session_start
();// must have a session, duh...

class foo{//normal class declaration

 
var $bar;

  function
foo(){//normal constructor
  
$this->bar = "a value to share and persist";
  }
}

$vital = new foo;//instance "vital" of object type "foo"

session_register("vital");//register the instance "vital"

//other code as needed

?>

**NOTE: it would be helpful to include the class from an external source so the same declaration could be used everywhere its needed, duh

then simply include the class declaration in any other file and you will have access to the registered class instance.  in a separate frame on the same page you could use ...

<?
session_start
();

class
foo{//same class declaration

 
var $bar;

  function
foo(){//normal constructor
  
$this->bar = "a value to share and persist";
  }
}

echo
$vital->bar;

?>

**NOTE: if you use a frameset you must allow processing time of the session registration or the value will not be available!  You can use any number of methods to trigger the delay, but the session must NOT be started on the second page beforre the variable is registered on the first.  On option is to use an onload statement in the first frames body tag, assuming normal html output...

<html><head></head><body onLoad="parent.frame[1].location.reload();"><!--what ever else you need to output--></body></html>

"frame[1]" assumes a two frame layout with frame[0] containing the values to share and frame[1] requiring those values. thus this, when included in frame[0] will force a reload of frame[1] AFTER the class instance was registered.
mcoakley at netplay dot net
18-Jan-2003 12:47
In response to the comments above and using tomcats example directly... I love scripting languages and I love PHP the most out of them. While most programmers (and editors notes) try to state that PHP is not a true OO language it has what you need to develop good OO programs. Sure some of the really strong structured things aren't there but that is the fun you get with scripted languages. But after reading every comment on this page I think people (and I know I am going to get flamed for this one...) should start to fully understand the principles of OO programming: Encapsulation, Polymorphism and Abstraction.

For those new to those terms:
- Encapsulation is what you get when you can have data and the methods that act on those data in an "encapsulated" entity (object)
- Polymorphism is a property of objects that comes through inheritence that allows methods of the same name to perform different (but similar in purpose) actions
- Abstration provides a mechanism to design effective OO heirarchies by pulling common methods or actions into superclasses and using inheritence to provide functionality

If these principles are understood fully, PHP can be used as a great OO language.  Another common complaint is that PHP doesn't offer private/protected members/methods, I too would like to see these features. One BIG thing to keep in mind while desiging an OO program is that the objects should provide funtionality at the class level. Don't think of objects as individual entities but think of a heirarchy that provides "blackboxes" of code. In otherwords the class names should tell you what the object does and the methods only tell you how to invoke the functionality. You should never be concerned with how the object achieves its functionality.
b dot ruecker at portunity dot de
09-Jul-2001 12:22
If you need a destructor, perhaps it is an idear to simulate it this way with a global Destroy-Function:

<?
function DestroyObject ($name)
{
    
$theobject = &$GLOBALS[$name];
     if (
method_exists ($theobject,"Destroy"))
        
$theobject->Destroy ();
     unset (
$GLOBALS[$name]);
}

class
xyz
{
   var
$somevar;

  
// ### This is the constructor
  
function xyz ()
   {
   }

  
// ### This is the destructor which will be called
  
function Destroy ()
   {
       echo (
"Now we destroy it !");
   }

   function
SomeDo ()
   {
       echo (
"doing something: ".$this->somevar);
   }
}

$example = new xyz;

// .... doing something here
$example->somevar = 3;
$example->SomeDo();

DestroyObject ("example");

// ### Test => should produce an error !
$example->SomeDo ();

?>
sgarner at expio dot co dot nz
19-Feb-2001 10:15
[Editor's note: Remember tha PHP is not a hard core OOP language, and even the ones that are do not always support the unusual vector/array references applied to results from methods.]

It seems there is no way to access the return value of a method (or any function) inline, without assigning it to a variable.

For example:

<?php
class Test
{
  function
blah ()
  {
     return array(
1,2,3);
  }

  function
childTest ()
  {
     return new
Test;
  }
}

$test = new Test;

// This does not work:
$foo = $test->blah()[0];

// Instead have to do:
$temp = $test->blah();
$foo = $temp[0];

// Similarly for objects, cannot do:
$foo = $test->childTest()->blah();

// Instead have to do:
$temp = $test->childTest();
$foo = $temp->blah();

?>
buzz77 at gmx dot net
15-Feb-2001 12:33
You can also store object variables as session variables, so that you don't have to create an object every time the page loads.

Let's see how:
here is my simple class file:

// simple.lib.php
class simple
{
  function dummy
  {
   print "TEST SUCCESSFUL!\n";
  }
}

Then, I create a simple .php which starts a new session and registers the object-variable of the "simple"-class.

// test1.php
require ("simple.lib.php");
session_start();
session_register("CLASSOBJ");
$CLASSOBJ=new simple();

That's all.
In the following .php-files you've only to add the following lines:
require("simple.lib.php");
session_start();

To test out if it works, simply call:
$CLASSOBJ->dummy();
and it will print the message.

I tried it out also with quite huge classes, and it always worked (I think the pointer to the instanciated class is stored and the class object itself won't be deleted if you eg. change to another .php-page)
brice at webprojkt dot com
22-Dec-2000 01:23
Defaulting a function parameter to a variable isn't directly supported, but here's how to get around that:

Suppose you have a class:

class query {
   var $sql;
   var $link;

   function go ($SQLstring = $this->sql)
   {
     return mysql_query($this->sql,$link);
   }
}

This doesn't work.  Here's the workaround:

(function spec):
   function go ($SQLstring)
   {
     if (isset($SQLstring)) { $this->sql = $SQLstring; }
     return mysql_query($this->sql,$this->link);
   }

This may not be the best example of this, but I thought I'd throw this out for you folks ... should allow support of presetting of an object value and then execution of the method on that, or something like query::go("SELECT ...");

Enjoy!

p.s. (in this case query::go wouldn't work because it is coded with $this->link, but if you wanted to just use the default connection, it'd work fine :)
iw at warped dot nu
09-Oct-2000 08:12
Here's a very important reminder to those of you used to Java/C++ object references/pointers. When you send a function arguments which include a class object, PHP will make copies of that object for use inside that function.

This differs from passing a Java reference to an object or passing a C++ pointer to an object. Within the scope of the above-mentioned function, calling class methods of the argument object will only affect the copy that PHP creates. Likewise, when the function itself is completed, the copy of the object you passed ceases to exist.

To emulate Java/C++ functionality of arguments that are objects, you just have to modify the given function's signature from this:

function foo(..., $object, ...)

to this:
function foo(..., &$object, ...)

The ampersand(&) thus signifies that the function should receive a reference to the object, instead of creating a copy of the object.
simon dot li at hongkong dot com
14-Sep-2000 07:15
-------------------------------------------------
[Editor's note: class casting per se is not part of the object/class implementation in PHP, but code like the one in this note can kludge if you need it for very simple cases, more complex ones are left to the imagination of the programmer:
<?php
class foo {
   function
foo($name="foo") {
      
$this->name=$name;
   }
}

class
bar extends foo {
   function
boom() {
       echo
"BOOOM!";
   }
}

$f = new foo();
$temp = explode(":",serialize($f));
$temp[2] = "\"bar\"";
$b = unserialize(implode(":",$temp));

$b->boom();

?>
This forces $b to be an instance of "bar" using an object $f, an instance of "foo"]
-------------------------------------------------


About casting of object, say, i got:

class A extends B {
       function A() {
               $this->B();
       }
       ....
}

$b = new B();
$a = new A();

I wanna have a object of class A with "content" of $b:
$a = (A) $b; // not a valid code,(right?) as for illustration.