PHP  
downloads | documentation | faq | getting help | mailing lists | reporting bugs | php.net sites | links | my php.net 
search for in the  
<Internal (built-in) functionsextends>
view the version of this page
Last updated: Thu, 21 Aug 2003

Chapter 13. Classes and Objects

class

A class is a collection of variables and functions working with these variables. A class is defined using the following syntax:

<?php
class Cart
{
    var $items;  // Items in our shopping cart
   
    // Add $num articles of $artnr to the cart
 
    function add_item ($artnr, $num)
    {
        $this->items[$artnr] += $num;
    }
   
    // Take $num articles of $artnr out of the cart
 
    function remove_item ($artnr, $num)
    {
        if ($this->items[$artnr] > $num) {
            $this->items[$artnr] -= $num;
            return true;
        } else {
            return false;
        }   
    }
}
?>

This defines a class named Cart that consists of an associative array of articles in the cart and two functions to add and remove items from this cart.

Warning

You can NOT break up a class definition into multiple files, or multiple PHP blocks. The following will not work:

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

The following cautionary notes are valid for PHP 4.

Caution

The name stdClass is used interally by Zend and is reserved. You cannot have a class named stdClass in PHP.

Caution

The function names __sleep and __wakeup are magical in PHP classes. You cannot have functions with these names in any of your classes unless you want the magic functionality associated with them. See below for more information.

Caution

PHP reserves all function names starting with __ as magical. It is recommended that you do not use function names with __ in PHP unless you want some documented magic functionality.

In PHP 4, only constant initializers for var variables are allowed. To initialize variables with non-constant values, you need an initialization function which is called automatically when an object is being constructed from the class. Such a function is called a constructor (see below).

<?php
/* None of these will work in PHP 4. */
class Cart
{
    var $todays_date = date("Y-m-d");
    var $name = $firstname;
    var $owner = 'Fred ' . 'Jones';
    var $items = array("VCR", "TV");
}

/* This is how it should be done. */
class Cart
{
    var $todays_date;
    var $name;
    var $owner;
    var $items;

    function Cart()
    {
        $this->todays_date = date("Y-m-d");
        $this->name = $GLOBALS['firstname'];
        /* etc. . . */
    }
}
?>

Classes are types, that is, they are blueprints for actual variables. You have to create a variable of the desired type with the new operator.

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

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

This creates the objects $cart and $another_cart, both of the class Cart. The function add_item() of the $cart object is being called to add 1 item of article number 10 to the $cart. 3 items of article number 0815 are being added to $another_cart.

Both, $cart and $another_cart, have functions add_item(), remove_item() and a variable items. These are distinct functions and variables. You can think of the objects as something similar to directories in a filesystem. In a filesystem you can have two different files README.TXT, as long as they are in different directories. Just like with directories where you'll have to type the full pathname in order to reach each file from the toplevel directory, you have to specify the complete name of the function you want to call: In PHP terms, the toplevel directory would be the global namespace, and the pathname separator would be ->. Thus, the names $cart->items and $another_cart->items name two different variables. Note that the variable is named $cart->items, not $cart->$items, that is, a variable name in PHP has only a single dollar sign.

<?php
// correct, single $
$cart->items = array("10" => 1); 

// invalid, because $cart->$items becomes $cart->""
$cart->$items = array("10" => 1);

// correct, but may or may not be what was intended:
// $cart->$myvar becomes $cart->items
$myvar = 'items';
$cart->$myvar = array("10" => 1);  
?>

Within a class definition, you do not know under which name the object will be accessible in your program: at the time the Cart class was written, it was unknown that the object will be named $cart or $another_cart later. Thus, you cannot write $cart->items within the Cart class itself. Instead, in order to be able to access it's own functions and variables from within a class, one can use the pseudo-variable $this which can be read as 'my own' or 'current object'. Thus, '$this->items[$artnr] += $num' can be read as 'add $num to the $artnr counter of my own items array' or 'add $num to the $artnr counter of the items array within the current object'.

Note: There are some nice functions to handle classes and objects. You might want to take a look at the Class/Object Functions



add a note add a note User Contributed Notes
Classes and Objects
nathan at newmediasolutions dot ca
24-Oct-2003 04:44
Under PHP Version 4.2.2 classes that do not contain variables will be considered NULL when they are initialized.

class A {
  function A() {
  }
}

class B {
  var $b;
  function B() {
  }
}

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

print( "<br />( a == NULL ): " . ($a==NULL) );
print( "<br />( b == NULL ): " . ($b==NULL) );

The output for this will be:
( a == NULL ): 1
( b == NULL ):
baZz
16-Oct-2003 05:02
If you want to use a class within different pages there is more than one way to do it. The first one is documented in a note above by russ, the only problem with this method is that you must have register_globals = ON (in php.ini) and the php recomendation is to set it to off. The other way is using session array:

<?php /*Page 1*/
session_start();
/*class declaration*/
class Employee{
  var 
$name;
  var 
$lastname;
  function 
newEmpl($name,$lname,$noemp){
   
$this->name[$noemp] = $name;
   
$this->lastname[$noemp] = $lname;
  }
  function 
getEmpl($noemp){
    return 
$this->name[$noemp];
  }
}

$myempl = new Employee;
$myempl->newEmpl('Peter','Gabriel',0);
$myempl->newEmpl('Alex','Bowie',1);
$_SESSION['myempl'] = $myempl/*Here we add our var to the session array*/
echo "<a href=\"testemp2.php\">go next page to test our class</a>";
?>

<?php/*Page 2*/

session_start();
echo 
"<p>Testing our class</p><br \>";

class 
Employee{
  var 
$name;
  var 
$lastname;
  function 
newEmpl($name,$lname,$noemp){
   
$this->name[$noemp] = $name;
   
$this->lastname[$noemp] = $lname;
  }
  function 
getEmpl($noemp){
    return 
$this->name[$noemp];
  }
}
echo 
$_SESSION['myempl']->getEmpl(0);/*This should print the name of the first employee that we add in the other page*/
?>

After this you can use the object within the whole session.
Good Luck.
Micha
07-Oct-2003 02:42
When you want to initialize constant variables, don't add multiline arrays.

Ex. This will NOT work

var $alt = array( "opt1" => array(), "opt2" => array() );
var $alt["opt1"][0] = "on";
var $alt["opt1"][1] = "off";
var $alt["opt2"][0] = "yes";
var $alt["opt2"][1] = "no";

You need to write all in one line.

Ex. This will work

var $alt = array(
    "opt1" => array("on", "off"),
    "opt2" => array("yes", "no") );
spamspam at linuxmail dot org
29-Jul-2003 08:46
Here's an example of how I use the Factory Pattern and dynamic class loading & instantiation (note that I'm useing the forcetype trick to encode the resource requested in the URL as part of the path):

<?php

class Factory {
    var 
$pcon;
    var 
$qstr "select
        ClassName,ClassFile from
        Resources inner join ResourceTypes
        on Resources.ResourceType = ResourceTypes.id
        where ResourceName='%s';"
;

    function 
Factory(){
       
$this->pcon pg_pconnect("dbname=RCMS");
    }

   function 
Generate(){   
       
$urlArray explode("/",$_SERVER["REQUEST_URI"]);
       
$tmp explode("?",$urlArray[2]);
       
$resource $tmp[0];

       
$qr pg_query(
           
$this->pcon,
           
sprintf($this->qstr,pg_escape_string($resource))
        );

        if(
$ra pg_fetch_row($qr)){
            require(
$ra[1]);
            return new 
$ra[0](pg_escape_string($resource),$this->pcon);
        };

       require(
"NotFound.class.php");
        return new 
NotFound();
    }

}

$ItemFactory = new Factory();
?>
arnsholt at online dot no
06-Jul-2003 04:39
In a recent project of mine I needed a linked list, but as there are no pointer variables in PHP, I came up with the following kludge using array indexes instead of memory adresses:

<?php
/* the null pointer is represented by the integer value 0, indexes(/memory adresses) are assigned starting at 1 */
   
class linkable
   
{
        static 
$first;

        var 
$prev;
        var 
$next;

        var 
$dust_puppy;

       function 
linkable $f_prev$data )
        {
           
$this->prev $f_prev;
           
$this->dust_puppy $data;
           
$this->next 0;
        }
    }

   
linkable::$first 1;
   
$linked_list = Array ( );

     function 
new_item $data )
     {
        if ( !
$linked_list [linkable::$first] )/* we need to capture an empty list */
       
{
           
$linked_list [linkable::$first] = new linkable;
        return;
        }

       
$item linkable::$first;
        while ( 
$linked_list [$item]->next )
           
$item $linked_list [$item]->next;

       
$linked_list [$item 1] = new linkable $item$data );
    }
?>
redshift at pandora dot be
05-Jul-2003 12:43
Hi,

You can use functions you defined in your class in another function of your class.
Like this:

class foo
 {
 var $string;
 function bar($string)
  {
  return $string;
  }
 
  function foodbar()
  {
  $return = foo::("hello world");
  return $return;
  }
 }

To execute it:
<?php
$myfoo 
= new foo;
echo 
$myfoo->foodbar();
?>
would produce:
hello world
mazsolt at yahoo dot com
04-Jul-2003 11:42
The $this reference means the current object, which calls the function or property. If we call from the derived class with the :: operator a function defined in the base class , $this will represent the object of the derived class:

class a{
 var $a=1;
 function display(){
   echo $this->a;
 }
}

class b extends a{
 var $a=9;
 function disp(){
  a::display();
 }
}

$x=new b;
$x->disp();

It will display 9.
keto at mesmer dot com
25-Jun-2003 08:18
I experienced the following error:

__PHP_Incomplete_Class Object (......)

The problem arose from calling a session variable which had not been defined in my code. When using session and objects and you see this error, check if the class has been defined and then try using ini_set() if it was not successful.
oran at anonimous dot biu dot ac dot il
24-Jun-2003 07:59
The editor's suggestion for using the predefined constant __CLASS__ for interaction between static functions is incorrect. __CLASS__ gives the name of the class where the method that uses it is defined, and NOT the name of the extending class that is actually in use.

Therefore, the following code on PHP 4.3.0 prints "baseclass, bla" and not "subclass, foo":

class baseclass {
  function static1() {return "bla";}
  function static2() {
     return __CLASS__ . ', ' .
     call_user_func(array(__CLASS__,'static1'));
  }
}
class subclass extends baseclass {
  function static1() {return "foo";}
}
print subclass::static2();
lachtan
18-Jun-2003 01:25
Static class variable

class Test {
  var $variable; // will be static class variable

  function Test {
    static $variable;
    $this->variable =& $variable;
  }

  function id() {
    return (int) $this->variable++;
  }
}

$a = new Test();
$b = new Test();
echo($a->id());
echo($b->id());
oran at anonimous dot biu dot ac dot il
17-Jun-2003 12: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.
chris at dontwantspam dot com
23-Apr-2003 01:29
Even though you can't set a default value for an argument like this:

function foo($bar = 'rar') {
  // do stuff
}

You can use the func_get_arg, func_get_args, and func_num_args on class methods.

function foo() {
  $bar = func_num_args >= 1 ? func_get_arg(0) : 'rar';
}
russ dot taylor at nifty dot com
18-Apr-2003 03: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.
rjkaes at flarenet dot com
05-Apr-2003 11:30
The note and example indicates that arrays cannot be used to initialize class variables, but I've used the following code without a problem:

class Foo {
    function print_field($n)
    {
        print $this->_fields[$n];
    }

    var $_fields = array('field1', 'field2', 'field3');
}

$foo = new Foo;
$foo->print_field(1);

Perhaps the note/example in the documentation needs to be clarified.
twoch
08-Feb-2003 04:38
As noted in another section of this user manual, the variable $this refers to the innermost encompassing class. 

If you invoke a method on class A from and instance of A, and from within that method invoke a method in class B using the "::" syntax (i.e. invoked as a class method), if the method within B uses $this it will refer to the instance of class A that called it. 

Note that this behavior is very different from the case where the same B method is invoked using and instance of class B, in which case $this refers to the instance of class B.

This can cause no end of grief when trying to debug such object methods that were invoked as class methods (although it can also be a powerful tool when used correctly).  However, IMHO, any method that might be invoked as a class method should refrain from the use of $this.
phil at philkern dot de
26-Jan-2003 11:43
Subclasses inside of classes are not possible :/
Something like that (which would help to keep the code a bit cleaner) you would have to do in an other way:

class SomeClass {
  class Debug {
   function Log($text) {
    echo $text;
   }
  }

  function some_function() {
   SomeClass::Debug::Log($text); // Error
   }
}

So you can't built up perl alike constructs :)
jp at antz29 dot com
25-Jan-2003 02:17
ok, found a simple way to implement static class variables. this method may be frowned upon by anyone and everyone but it worked fine for me and is certainly more readable than 99% on alternatives that i have looked into. see below.

class A {
    #this is going to be my static class variable.
    var $foo;
     
    function A() {
    #define a global for my static variable.
    #prepend the class name to the var name for clarity.
        global $A_foo;
       
        #and refrence it to my class variable.
        $this->foo =& $A_foo;
    }
   
    function setfoo($val) {
        $this->foo = $val;
    }
   
    function getfoo() {
        return $this->foo;
    }
   
}

#create two instances of the A object.
$foobar1 = new A;
$foobar2 = new A;

#set the first object's foo to bar.
$foobar1->setfoo('bar');

print "FOO-1 = ".$foobar1->getfoo()."<br>";
print "FOO-2 = ".$foobar2->getfoo()."<br>";

/*
This outputs:
    FOO-1 = bar
    FOO-2 = bar
*/

#and just to make my point clear, set the second object's foo to foobar.
$foobar2->setfoo('foobar');

print "FOO-1 = ".$foobar1->getfoo()."<br>";
print "FOO-2 = ".$foobar2->getfoo()."<br>";

/*
This outputs:
    FOO-1 = foobar
    FOO-2 = foobar
*/

see ist't that fantastic? feel free to e-mail me with any comments/questions.
mcoakley at netplay dot net
18-Jan-2003 12:48
Here is the example I promised...

//Abstract class - should never be instantiated
class FormField {
  var $name;
  var $value;
  var $style;

  construction FormField($name, $value, $style = "") {
    $this->name = $name;
    $this->setValue($value);
    $this->setStyle($style);
  }

  function setValue($value) { $this->value = $value; }
  function getValue() { return $this->value; }
  function getName() { return $this->name; }
  function setStyle($style) { $this->style = $style; }
  function getStyle() { return $this->style; }
 
  //Polymorphism - this method is the main polymorphic point
  function displayField() { echo "YOU MUST OVERRIDE!!!"; }
 
  function getDisplayStyle() {
    if ($this->style=="") {
      return "";
    } else {
      return " style=\"$this->style\"";
    }
}

class TextInputField extends FormField {
  var $maxlength;
  var $size;

  function TextInputField($name, $value, $style = "", $maxlength = 255, $size = 20) {
    $this->FormField($name, $value, $style);
    $this->maxlength = $maxlength;
    $this->size = $size;
  }

  function displayField() {
    echo "<input name=\"$this->name\" size=\"$this->size\" maxlength=\"$this->maxlength\"" . $this->getDisplayStyle() . " value=\"$this->value\">";
  }
}

//Another abstract class
class CheckboxRadioField extends FormField {
  var displayName;
  var selected;

  function CheckboxRadioField($name, $value, $displayName, $style = "") {
    $this->FormField($name, $value, $style);
    $this->displayName = $displayName;
  }

  function setSelected($selected) { $this->selected = $selected; }
  function isSelected() { $this->selected; }
 
  function getDisplaySelected() {
    if ($this->isSelected()) {
      return " checked";
    } else {
      return "";
    }
  }

}

class CheckboxField extends CheckboxRadioField {
  function CheckboxField ($name, $value, $displayName, $style = "") {
    $this->CheckboxRadioField($name, $value, $displayName, $style);
  }

  function displayField() {
    echo "<input type=\"checkbox\" name=\"$this->name\" value=\"$this->value\"" . $this->getDisplaySelected() .  $this->getDisplayStyle() . ">$this->displayName";
  }
}

class RadioField extends CheckboxRadioField {
  function RadioField ($name, $value, $displayName, $style = "") {
    $this->CheckboxRadioField($name, $value, $displayName, $style);
  }

  function displayField() {
    echo "<input type=\"radio\" name=\"$this->name\" value=\"$this->value\"" . $this->getDisplaySelected() . $this->getDisplayStyle() . ">$this->displayName";
  }
}

//Now a quick usage example
$fields[] = new TextInputField("text1", "Hello World", "", 40);
$fields[] = new CheckboxField("checkbox1", "option_1", "Click here for option #1");
$fields[] = new RadioField("radio1", "rad_option_1", "Polished");
$fields[] = new RadioField("radio1", "rad_option_2", "Rough");

echo "<form action=\"form_handler.php\" method=\"post\">";
for ($i = 0; $i < count($fields); $i++) {
  //Polymorphism at its best
  $fields[$i]->displayField();
}
echo "</form>";

Sorry for the long post but I just thought it could help...
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. To demonstrate these principles more fully (and please do not take this as a finite example) I will create a real simple form building object heirarchy.

Post is too long, so example will be my next post...
tomcat at techie dot com
06-Jan-2003 10:39
The fact that PHP does not support variable types, leads to new opportunities. You can make an object-collection with different classes of objects, extremely easily (pay attention to posession collection of merchant object):

[example]

class user {

    var $login;
    var $email;
    var $password;

    function user ( $login, $email, $password ) {
        $this->login = $login;
        $this->email = $email;
        $this->password=$password;
    }

}

class house {
    var $price;
    var $area;

    function house () {
        $this->price = 10000000000;
    }
}

class car {
        var $price;
        var $speed;
        var $length;
        var $color;

        function car () {
          $this->speed = 300;
        }
}

class merchant {
        var $age;
        var $personality;
        var $posession;

        function merchant () {
                $this->age=27;
        }
}

$oMerchant = new merchant();
$oMerchant->personality = new user("name","pas","email");
$oMerchant->posession[] = new car();
$oMerchant->posession[] = new house();

echo "
<pre>
car-speed: ".$oMerchant->posession[0]->speed."
house-price: ".$oMerchant->posession[1]->price."
</pre>
"
[/example]

It's real cute, how easy it is compared to strictly-typed languages (well, it's less clean but so is everything in non-typed languages, right?).
tomcat at techie dot com
04-Jan-2003 05:48
Creating Object collection is very easy in PHP. Actually, regular array can serve as one:

class user {

    var $login;
    var $email;
    var $password;

    function user ( $login, $email, $password ) {
        $this->login = $login;
        $this->email = $email;
        $this->password=$password;
    }

}

$arrOBJ = array(); //This line is unnecessary, I would just use it to make code more readable. You can remove.
$arrOBJ[] = new user("1","1","1");
$arrOBJ[] = new user("2","2","2");

echo "success: ".$arrOBJ[0]->login;
Michael Berndt
23-Dec-2002 01:22
acsguy at wtp dot net
20-Dec-2002 06:29
If you want to store class objects in the $_SESSION variable so that pages and scripts that follow are able to access the class without having to re-create the class each time a new page or script loads, you might also want to write some helper functions to make the code easier to use.  I struggled for a week trying to write one that worked.  The main problem I was running into was wanting the function to return a reference to the class object stored in  $_SESSION.  You cannot use the & operator with the return statement.

// error
return &$_SESSION["class"];

//if you use a variable to get past the error, you get a copy.
// NOT a refference
return $var = &$_SESSION["class"];

[solution]
I found the solution here
http://www.dynamic-webpages.de/70.php_4-0-4_ChangeLog.php

what it entailed is declaring the function itself as returning a reference e.g.

function &get_class_ref("class_name"){
   return $_SESSION["class_name"];
}

if you call the function like this it STILL passes a copy

// still won't work
$class = get_class_ref("class_name");

//BUT if you also include the & operator it WILL WORK
$class = &get_class_ref("class_name");

//here is a part of my helper functions for clarity

function class_pointer($c_name){
    if (empty($c_name)) return false;
   
    if (is_object($_SESSION["classes"][$c_name])){
        return true;
    }else{
        $test = new $c_name;
        $_SESSION["classes"][$c_name] = $test;
    }
   
    return true;
}

function &load_class($c_name){
    switch($c_name){
    case "c_dbase":
        if (class_pointer("c_dbase")){
            if (!$_SESSION["classes"]["c_dbase"]->connect()){
                $_SESSION["classes"]["c_page"]->display();
                exit();
            }
            return $_SESSION["classes"]["c_dbase"];
        }else{
            $_SESSION["classes"]["c_page"]->add("Couldn't create class c_dbase");
            $_SESSION["classes"]["c_page"]->display();
            exit();
        }
        break;
    }
}

// and is used like this
$cdb = &load_class("c_dbase");

[/solution]

hope this helps!

FYI  if you create a class from within another class method and set a class property by reference to the created class, php will COPY the class, not by reference like you would expect.  if you assign the property by reference from another seperate method call, it will do what you expect......

e.g.
// this will be by VALUE: $this->class is a COPY
class this()
{

var $class;

function getclass(){
   $_SESSION["class"] = new class();
   $this->class = &$_SESSION["class"];
}
}

// this DOES work:  $this->class is a referenc to the one
//stored in $_SESSION but takes 2 SEPERATE calls
class this()
{

var $class;

function make_class(){
   $_SESSION["class"] = new class();
}

function assign_class(){
   $this->class = &$_SESSION["class"];
}
}
Michael Berndt
18-Dec-2002 01:33
<?
// some array examples
// it works!

$Berndt = array('Dozent'=> 'PHP','Linux' => 'AWK, Sed');

class 
Berndt {
var 
$Berndt = array('Michael''Berndt''phpinfo',
' http://www.michael-berndt.de/ie/phpinfo/colour.php ');

var 
$Michael = array('Michael'=> 'Berndt',
'Berlin' =>' http://www.michael-berndt.de/ie/phpinfo/phpinfo.php ');

function 
Michael(){
global 
$Berndt;
echo 
"<pre>";
print_r($Berndt);
echo 
"\n" .$Berndt['Dozent']. "\n";
print_r($this->Berndt);     // integer-indices
echo "\n" $this->Berndt[0] ."\n";
echo 
"\n"$this->Michael["Berlin"] ."\n\n";
print_r($this->Michael);    // key/value pairs
echo "</pre>";
}

// End class Berndt
$objekt = new Berndt();
$objekt->Michael();
?>
<?
/* PHP Version >= 4.1.2: */?>
duncan at NOTINNED dot MEAT dot emarketeers dot com
09-Dec-2002 11:55
If you want to use class variables you should use a static method, not a global as suggested above.

class Counter {
  function Counter($name) {
    $this->name = $name;
    $this->id = Counter::id();
  }

  function &_classObj() {
    static $classObj;
    if(!is_object($classObj)) {
      $classObj = new stdClass();
      $classObj->id=0;
    }
    return $classObj;
  }

  function id() {
    $co =& Counter::_classObj();
    $co->id++;
    return $co->id;
  }

  function sayHello() {
    echo "Hello, I am $this->name and my ID is $this->id\n";
  }
}

$a = new Counter("Bill");
$b = new Counter("Ben");

$a->sayHello();
$b->sayHello();

**** Prints ****

Hello, I am Bill and my ID is 1
Hello, I am Ben and my ID is 2
duncan at NOTINNED dot MEAT dot emarketeers dot com
09-Dec-2002 11:48
You *can* return a reference from a constructor. You just need to understand exactly what the "=" and "=&" operators do. Try this:

class parent
{
   var $child;
   function parent($name)
   {
       $this->name = $name;
       $this->child =& new child($this);
 }
}

class child
{
   var $parent;
   function child(&$parent)
   {
       $this->parent = &$parent;
   }
}

$p = new parent("a");
$p->child->parent->name="b";
echo "Name = $p->name\n";  // Prints "a"

$p =& new parent("a");
$p->child->parent->name="b";
echo "Name = $p->name\n"; // Prints "b"

***
It seems that when a class constructor is called, PHP creates a new instance of the class and then either hands back a reference to this instance if you use the =& assignment operator, or creates and hands back a whole new copy if you use the plain = assignment operator.

You should assign new instances with the =& operator unless you have a good reason not to, because it is faster.
ronherhuth at mindspring dot com
06-Dec-2002 03:58
I was dissappointed to find that PHP didn't support multiple constructs like Java does.  In short in Java you can create multiple constructs all named the same, and based on the number of variables passed when creating a new object the appropriate construct is used to initialize the object.

I stumbled on a way to do this using an array:

class table
{
    function table($aTableStyles)
    {
    // SET DEFAULT VALUES
    $this->titleBar = "off";
    $this->titleBarBGColor = "#cccccc";
    $this->titleBarFontFace = "#Times New Roman";
    $this->titleBarFontColor = "#ffffff";
   
    // OVERRIDE DEFAULT WITH USER SET VALUES
    while (list($key, $val) = each($aTableStyles) )
        {
            $this->$key = $val;
        }
       
    }

}

// CREATE NEW OBJECT 1
// set values to send to constructor
$aTableStyles1 = array(
    "titleBar" => "on"
)

$newTable1 = new table($aTableStyles1);

// CREATE NEW OBJECT 2
// set values to send to constructor
$aTableStyles2 = array(
    $this->titleBarBGColor = "#cccccc";
    $this->titleBarFontFace = "#Times New Roman";
    $this->titleBarFontColor = "#ffffff";
)

$newTable2 = new table($aTableStyles2);

--

Basically what I have done is created four class variables that hold default values.  When the constructor is called you can choose to override the default values by passing any number of values in an associative array.  The constructor simply loops through and replaces any of the default variables with user supplied ones.  This way when a new object is created you can chose to override only a single value or all of them.  This was very important in my table class because I had 30+ options the user could choose to override.

Ron
smurge at REMOVETHISweb dot de
01-Nov-2002 03:13
The workarounds for chaining/inheriting constructors in here didn't work for me when I tried them. After a while, I found a different way to make sure the parent class constructor was called: Unserializing the child class instance from a (new) parent class instance and then executing its own initialization:

<?php

...

class 
THECHILD extends THEPARENT {

    var 
$abc;
    var 
$xyz "xyz"// NOTE: this value will be lost during unserialization

   
function _ATOM() {

       
// NOTE: $this->xyz is now "xyz"
       
$this unserialize (serialize (new THEPARENT()));
       
// NOTE: Original value of $this->xyz is lost

       
$this->$abc "abc"// Better: initialize values after ser/unser. step
   
}
}

...

?>

Not the fastest to execute maybe, but it seems (!) to work fine.

The pro's:
- Not as much typing and
- Not as confusing to read
as some other solutions I've found.
skynet at context-ua dot com
10-Oct-2002 05:35
[Note: here is a trick with inheritance. Consider we have object named 'b' that extends object 'a'. But we would like to call a function 'b::handle' right from object 'a'. The following code will do the trick.]
<?php
 
class {
  function 
(){
   echo 
"Class a construct<br>";
  }

  function 
handle() {
   echo 
"Class a handle<br>";
  }

  function 
proceed() {
   
$this->handle(); //actually b::handle is called here;
   
echo "Class a proceed<br>";
  }
 }

 class 
extends {
  function 
(){
   
parent::a();
   echo 
"Class b construct<br>";
  }

  function 
handle(){
   echo 
"Class b handle<br>";
   
parent::handle();
  }
 }

 
$varriable = new b();
 
$varriable->proceed();
?>
[Output:
 Class a construct
Class b construct
Class b handle
Class a handle
Class a proceed
]
dhoffutt-dontlike at spam-airmail dot net
23-Sep-2002 01:06
_SESSIONS and CLASSES / OBJECTS

One may instantiate an object as a session variable, however every single page that your object passes through must include the code of the class.

Example:

include("dbObject.php");
session_start();
if (!is_object($_SESSION['testdb']))
{
  $_SESSION['testdb']= new dbObject;
}
$_SESSION['testdb']->do_your_class_functions();

Bit o' trivia worth mentioning: I recently switched to Mozilla 1.1 from IE. When attempting to test multiple session instances from same workstation, each instance of Mozilla on the same workstation used the same session instance as the previous Mozilla. Netscape 6 does the same thing. So, to test multiple sessions simultaneously from a single workstation, use Internet Explorer.
hfuecks at pinkgoblin dot com
23-Aug-2002 12:55
If you want to convert an array (for example) to an object, you can do something like this, using the reserved stdClass for data;

<?php
$array 
= array ( "one" =>"red""two" => "blue" );
$object = new stdClass ();
foreach ( 
$array as $key => $val ) {
   
$object->{$key}=$val;
}

echo ( 
"<pre>" );
print_r $object );
echo ( 
"</pre>" );
?>
kpower at ardencompanies dot com
18-Jul-2002 03:35
To create an array of objects, try the following:
class Test{
  function Test($temp){
    $this->a = $temp;
  }
  function print_a(){
    echo $this->a;
  }
}

$myObj = array();
for($i = 0; $i < 10; $i++)
  $myObj[] = new Test($i);

$myObj[9]->print_a();

Granted there are many ways to create you array. This is just a quick example.
philip at cornado dot com
04-Jun-2002 01:14
Know of any basic tutorials on PHP Classes and OOP?
* http://www.faqts.com/knowledge_base/view.phtml/aid/7569
fschaper at zerodegree dot de
18-May-2002 01:18
Despite the comments above this works out very well for me

class CTest {
  function CTest() { }
  function go( $var ) {
     echo "Thats an ".$var;
  }
}

$cTest = new CTest;

$member = "go";
$class = & $cTest;

$class->$member( "whatever" );
philhassey dot maybe dot at at hotmail dot com
02-Mar-2002 02:52
When trying to use a dynamically named array in a class, be careful of how you access your dynamic array.

Incorrect:
$dynamic_name="myarray";

$this->$dynamic_name[0]="apples";
// Meant $this->m="apples";

$this->$dynamic_name[1]="oranges";
// Meant $this->y="oranges";

Correct way:
$dynamic_name="myarray";

$this->{$dynamic_name}[0]="apples"; 
// Meant $this->myarray[0]="apples";

$this->{$dynamic_name}[1]="oranges";
// Meant $this->myarray[1]="oranges";

The incorrect example written differently shows how you could interact with multiple dynamic variable names.
$dynamic_names=array("name_one","name_two");

$this->$dynamic_names[0]="apples";
// Meant $this->name_one="apples";

$this->$dynamic_names[1]="oranges";
// Meant $this->name_two="oranges";

However this example might be more clearly written as
$dynamic_names=array("name_one","name_two");

$this->{$dynamic_names[0]}="apples";
// Meant $this->name_one="apples";

$this->{$dynamic_names[1]}="oranges";
// Meant $this->name_two="oranges";
flash at minet dot net
06-Jan-2002 03:21
It's possible to 'redefine' a class using $this.

Check this example :
<?

class {
    function 
A() {
        print 
"<div>instance of A</div>";
    }
    function 
whoami() {
        print 
"<div>";
       
var_dump($this);
        print 
"</div>";
    }
}

class 
{
    function 
B() {
        print 
"<div>instance of B</div>";
    }

    function 
transform() {
       
$this = new A(); // <-- THIS line :)
   
}
    function 
whoami() {
        print 
"<div>";
       
var_dump($this);
        print 
"</div>";
    }
}

print 
"<div><b>Instanciations</b></div>";
$A = new A$A->whoami();
$B = new B$B->whoami();

print 
"<div><b>Transformation</b></div>";
$B->transform();
$A->whoami();
$B->whoami();
?>

First, we create two objects : $A -> class A, and $B -> class B.

But the method 'transform' redefines $B instances, and $B is now of class A.

(sorry, there are some problems with the layout)
dougqh at hotmail dot com
30-Oct-2001 06:29
If you want to call a method of class and you do not have an instance of the class and you have the class, method name, or both stored in a variable(s) you can use the following ...

call_user_func( array( $className, $functionName ), [ $param0 [, $param1 [, ... ] ] ] )

For example

$class = "MyClass";
$method = "myMethod";

call_user_func( array( $class, $method ), 0, 1 );

is equivalent to

MyClass::myMethod( 0, 1 );
promo at card2u dot com dot my
29-Oct-2001 09:56
A very simple class builder utility is at http://www.card2u.com.my/ClassBuilder
b dot ruecker at portunity dot de
08-Jul-2001 11: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 ();

?>
idont at remember dot it
24-Feb-2001 05:47
[Editor's note: Just a quick comment.

Inherently OO languages should theoretically access attributes using methods, but even in existing ones this is not strictly enforced. PHP is *not* and inherently OO language, but one that has some object/class support.

This note is talking about a "best practice" recommendation, not a necessity that is dictated by the language design or implementation.]


In many exemples (and in the official doc) I saw a problem: many access directly the attributs of the objects. Actually we SHOULD always access an attribut through a method.

<?php
class user{
  var 
$_name;
  var 
$_email;

  function 
user($name,$email){
   
$this->_name=$name;
   
$this->_email=$email;
  }

  function 
getName(){
    return(
$this->_name);
  }

  function 
getEmail(){
    return(
$this->_email);
  }

  function 
setName($name){
   
$this->_name=$name;
  }

  function 
setEmail($email){
   
$this->_email=$email;
  }
}

$me = new user("Bill","billclinton@whitehouse.org");
echo 
"my name is :".$me->getName()."&lt;br&gt;";
echo 
"and my email :".$me->getEmail()."&lt;br&gt;";

//wrong way
$me->_email="billclinton@retired.com";
//Better way
$me->setEmail("billclinton@retired.com");

//wrong way
echo "oops sorry, here is the right one:".$me->_email."<br>";
//Better way
echo "oops sorry, here is the right one:".$me->getEmail()."<br>";
?>

As you noticed I put a "_" at the beginning of the attributs' names, this is a typo tip to declare them as private. OF course this is not real as PHP doesn't support the notions of public, private for methods and attributs.
A poor solution waiting for a better one. :)
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:

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 :)
monsy2 at yahoo dot com
09-Nov-2000 09:33
It seems that when you use "extends", the definition of the extended classe must precede the use of "new", otherwise it whon't work.
Which is not the case with a not extended class. (php4)
eggbird at bigfoot dot com
02-Nov-2000 03:33
[Editor's note: This has to do with the ambiguity of the expression used. When the assignment fails it is because the expression could mean "the property 'tuut' of the object '$this->memberobject'" or "the property 'memberobject->tuut' of the object '$this'", parsing of variables inside quotes in which you have a complex expression is not recommended, the way it should be done is by using the concatenation operator, which is why the last assignment works. This is a know behaviour, see for example the "Variable variables" section of the manual.]


i might be wrong here, but to me it seems that (within a method) something like this:

$bla = "boink and $this->tuut";

does work, but not this:

$bla = "boink and $this->memberobject->tuut";

I had to resort to

$bla = "boink and ".$this->memberobject->tuut;

in this case.
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.

<Internal (built-in) functionsextends>
 Last updated: Thu, 21 Aug 2003
show source | credits | sitemap | mirror sites 
Copyright © 2001-2003 The PHP Group
All rights reserved.
This mirror generously provided by: http://php.mirrors.ilisys.com.au/
Last updated: Sat 01 Nov 2003 04:13:36 EST EST