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



PHP : Language Reference : Classes and Objects (PHP 4) : Constructors

Constructors

Constructors are functions in a class that are automatically called when you create a new instance of a class with new. A function becomes a constructor, when it has the same name as the class. If a class has no constructor, the constructor of the base class will be called, if it exists.

<?php
class Auto_Cart extends Cart {
   function
Auto_Cart() {
       
$this->add_item("10", 1);
   }
}
?>

This defines a class Auto_Cart that is a Cart plus a constructor which initializes the cart with one item of article number "10" each time a new Auto_Cart is being made with "new". Constructors can take arguments and these arguments can be optional, which makes them much more useful. To be able to still use the class without parameters, all parameters to constructors should be made optional by providing default values.

<?php
class Constructor_Cart extends Cart {
   function
Constructor_Cart($item = "10", $num = 1) {
       
$this->add_item ($item, $num);
   }
}

// Shop the same old boring stuff.
$default_cart = new Constructor_Cart;

// Shop for real...
$different_cart = new Constructor_Cart("20", 17);
?>

You also can use the @ operator to mute errors occurring in the constructor, e.g. @new.

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

   function
B()
   {
       echo
"I am a regular function named B in class A.<br />\n";
       echo
"I am not a constructor in A.<br />\n";
   }
}

class
B extends A
{
}

// This will call B() as a constructor
$b = new B;
?>

The function B() in class A will suddenly become a constructor in class B, although it was never intended to be. PHP 4 does not care if the function is being defined in class B, or if it has been inherited.

Caution:

PHP 4 doesn't call constructors of the base class automatically from a constructor of a derived class. It is your responsibility to propagate the call to constructors upstream where appropriate.

Destructors are functions that are called automatically when an object is destroyed, either with unset() or by simply going out of scope. There are no destructors in PHP. You may use register_shutdown_function() instead to simulate most effects of destructors.

Code Examples / Notes » language.oop.constructor

steffen-staehle

[in reply to ogarbe's comment (01-Apr-2003)]
Any object evaluation as boolean of the kind
<?
  if ($a = new A())
  {
    // success, use $a ...
  }
?>
is dangerous. Whether an object evaluates as true or false seems to depend on its internal structure (I've tested on a rather oldish version of php (4.2.1), though, so this might have changed!). Even a successfully created object might evaluate as false. Compare the two classes:
<?
class TestBool1
{
  var $somevar = 'hello world';
  function TestBool1()
  {
     echo "1 somevar is: $this->somevar

";
  } // constructor
} // TestBool
if ($obj = new TestBool1())
  echo 'obj is valid

';
else
  echo 'obj is invalid

';
class TestBool2
{
  function TestBool2($somevar)
  {
     echo "2 somevar is: $somevar

";
  } // constructor
} // TestBool
if ($obj = new TestBool2('hello world'))
  echo 'obj is valid

';
else
  echo 'obj is invalid

';
?>
The output is:
1 somevar is: hello world
obj is valid
2 somevar is: hello world
obj is invalid
Case '2' is NOT what you would expect.
So at least you should use another comparison:
<?
class TestBool3
{
  function TestBool3($somevar)
  {
     echo "3 somevar is: $somevar

";
     // assume error
     $this = NULL;
  } // constructor
} // TestBool
if (($obj = new TestBool3('hello world')) !== NULL)
  echo 'obj is valid

';
else
  echo 'obj is invalid

';
?>
This evaluates correctly and prints:
3 somevar is: hello world
obj is invalid
But Markus 16-Sep-2003 says assigning NULL to $this did not work any more with php 4.3.3. So what it boils down to: I still prefer the solution I have sketched below (steffen 17-Jan-2003).


sarjanwebdev

You can use a method of a subclass from a parent class.
class A{
function A(){
$this->say();
}
}
class B extends A{
function say(){
echo "Hi";
}

function B(){
self::A();
}
}
$b=new B();
prints "Hi"


john dot q dot webmaster

When testing the final example, I'm getting conflicting results with what the manual says.
-----
In PHP 3, the function B() in class A will suddenly become a constructor in class B, although it was never intended to be....
This is fixed in PHP 4 by modifying the rule to: 'A constructor is a function of the same name as the class it is being defined in.'. Thus in PHP 4, the class B would have no constructor function of its own and the constructor of the base class would have been called, printing 'I am the constructor of A.<br />'.
-----
I've just tested this on two systems, PHP (module) 4.3.7 and (CGI) 4.3.10.   BOTH of them print out the contents of B() when creating a new object of B.  This is contrary to the manual, which says this should only happen in PHP 3.
However, when testing the second to last example (where B() has no constructor), the behavior indicated for PHP 4 DOES happen; a constructor is called for 'new B', and it prints "I am the constructor of A.<br />".
What's happening here?


zax

to: steffen-staehle at NO dot SPAM dot gmx dot de
I got an error by
$this=NULL
(Fatal error: Cannot re-assign $this ...),
you should use
unset($this)
instead, that works


pigmeu

To workaround the problem that some people are having on multiple creator (or sub creators or whatever)...
Its just to use an event! Yes... U can emulate an event (like the inprize people do)
Here it goes:
<?
//This is the "generic" class... All other classes may extends from it...
class TObject {
   function On_Create() { }
   function TObject() {
       $this->On_Create();
   }
}
class TExtendedObject extends TObject {
   var $name;
   function On_Create() {
       $this->name = "Test";
   }
}
$t_class = new TExtendedObject;
echo $t_class->name;
/* output
Test
*/
?>
Nice... Isn't it?


ogarbe

to steffen staehle
If you want your constructor to possibly not create the object
class A
{
 function A()
 {
     // ...
     // some error occurred
     $this = null;
     return;  
 }
}
if ($a = new A())
{
 // success, use $a ...
}


31-mar-2004 03:50

to propagate the call to constructors, here is a good method :
class B extends A
{
var $var2;

function B ($arg)
{
parent::A();  // Invoke the constructor of the parent.
}
}


eric+nospam

This works in PHP 4.1.2 and probably versions > 4.x.
Creating an object from a constructor of a different class type can be accomplished.
Note that you can NOT return an object from a constructor.  A constructor can never return a value.  However, you can set the value of $this to acheive this.
For example:
<?
class A
{
 function A()
 {
   $this = new B();
 }
}
class B
{
 function iamab()
 {
   echo "i am an object of class B";
 }
}
$a = new A();
echo '$a is a ' . get_class($a) . "\n";
$a->iamab()
?>
would print out:
$a is a b
i am an object of class B


jfonseca

This will save you time if you're building a class hierarchy with 2 or more levels of inheritance.
$this always refers to the CURRENT INSTANCE. Therefore if you have:
class A{
  function A(){
  }
// ....
}
class B extends A{
  function B(){
    // keep these 2 lines in mind
    $parentClass = get_parent_class($this);
    $this->$parentClass();
  }
// ....
}
class C extends B{
  function C(){
    $parentClass = get_parent_class($this);
    $this->$parentClass();
    // here you will get into an infinite loop calling B();
  }
// ....
}
Explanation: $this is an instance variable referring to the CURRENT INSTANCE, therefore the $this variable on class B will always be an instance of C, therefore get_parent_class($this) in class B will call the constructor of C's parent class, which is B again.
This is a hard to track error if you're a novice on PHP's  OO features mainly because PHP will not produce any warnings, errors or notices, nor will it log anything to Apache or the error_log file.
Keywords : infinite recursion, parent constructor, subclass


arjini

This wasn't apparent in the docs above (wording maybe?)
class A{
  function A(){
      echo 'A\'s constructor has been called.';
  }
}
class B {function C(){}}
$instance = new B();
//output: A's constructor has been called.


23-jun-2004 11:48

This is for Ivan...
If this is the case then what is the case of the constructors of the child class being defined in the parent class...
they also get called implicitly on anyinstance of the child class


markus

Setting $this to null isn't available in PHP 4.3.3R3 anymore. Maybe in version below also.

mark

Responding to zax AT email DOT cz and others on the topic of pass/fail tests in constructors.
Later versions of PHP don't allow $this = null, so that's out.
Using unset($this) is allowed but is not reliable.
Consider the following:
class a {
function a($pass) {
if (!$pass) unset($this);
}
}

echo ($a = new a(true) ? "Passed" : "False") . "\n";
echo ($a = new a(false) ? "Passed" : "False") . "\n";
The output:
False
False
However, if you add a member variable to the class and run the same script, the output becomes:
Pass
Pass
Basically the object evaluates to false if there are no member variables, otherwise true.  I'm guessing, but I believe calling unset($this) only unsets the reference to the object.  A copy of it is still passed back to the calling code.
To sum up, I would stick with the original recommended solution of having a property specifically to represent an object's status: initialized or failed.
class A {
 var $success;
 function A() {
     if (/* some fail test */)
       $this->success = false;
     // rest of your construct
 }
}


dmarsh dot no dot spam dot please

Manual Destructor Example Code:
class MyObject()
 var $x;
 function MyObject() {
   $x=array();
   register_shutdown_function(array(&$this, "UnMyObject"));
 }
 [...]
 function UnMyObject() {
   unset($this->$x); // not needed but used to demonstrate the register_shutdown_function
 }
}


phpnotes

Just to possibly clarify something on this page: if you create an object of a derived class and the derived class has no constructor, then the base class's constructor will be automatically called.  For example:
<?php
class A {
   function A() {
       echo "A()\n";
   }
}
class B extends A {
   function foo() {
   }
}
$bar = new B;
// output: A()
?>
But if the derived class has a constructor, the base constructor is not automatically called.  For example:
<?php
class A {
   function A() {
       echo "A()\n";
   }
}
class B extends A {
   function B() {
       echo "B()\n";
   }
   function foo() {
   }
}
$bar = new B;
// output: B()
?>


mbrown

I found a reasonably neat way in PHP4 to solve the problem of calling superclass constructors without needing to embed knowledge of the entire class hierarchy into each class:
<?php
class A {
   function A () { $this->constructor(); }
   function constructor () {
       ....this is the "A" constructor body....
   }
}
class B extends A {
   function B () { $this->constructor(); }
   function constructor() {
       /* Call superclass constructor */
       parent::constructor();
       ....this is the "B" constructor body....
   }
}
?>
Note that the fact that class B inherits from class A is encoded in precisely one place: the "extends" clause, and is not duplicated within the class B constructor body, as would be the case had we used something more traditional:
<?php
class B extends A {
   function B() {
       $this->A();  /* "extends A" information would be duplicated here */
       ....this is the "B" constructor body....    
   }
}
?>


herojoker

Hi!
If you want to call the parent's constructor without knowing its name, just call
$this->{get_parent_class(__CLASS__)}($arg1, $arg2, ...);
Have fun with that.
Hero Wanders


dexen

Destructors aren't supported in PHP, and the sollution of using 'register_shutdown_function()' isn't really suitable for situations when you wan to perform destructor-alike finalization at a PARTICULLAR MOMENT, possibly way before exiting the PHP machine. (or sort of specialized serialization, as it's in my case).
Anyway, the general problem is to PROPAGATE a call through a hierarchy of objects, based on NAME PATTERN, in right ORDER (most_derived-to-most_base). Do not rely on INCLUSION of any CODE in derived classes. Do not assume EXISTENCE of any of 'destruction'  functions. Do support DEEP inheritance.
All i did was to create a _FINI_ function in base class, that calls a 'destructor alike' functions of pattern _%CLASSNAME_. Now, in order to 'destruct' (or serialize) i do  $OBJ->_FINI_(); then i can safely unset ($OBJ), all data is already saved to remote storage.
So, if ExSOMETHING derives from ExSession, which in turn derives from ExObject, i create _ExSOMETHING_ function in class ExSOMETHING and _ExObject_ in class ExObject. Notice there's no _ExSession_, yet nothing breaks.
Code:
<?php
class ExObject {
function _FINI_()
{
$p = get_class($this);
while( $p ) {
$px = '_'.$p.'_';
if ( method_exists($this, $px) ) {
$this->$px();
}
$p = get_parent_class( $p );
}
}
}
?>
You may want to create an interface class Destructable, include _FINI_ in it and derive all relevant classes from it.


johan_php

As far as I understand php has a strange way of handeling over loaded contructors - only the last defined will be used.
e.g.
class Cl {
 function Cl($a, $b) {
   echo("B ");
 }
 function Cl($a) {
   echo("A ");
 }
}
new Cl(1);
new Cl(1, 2);
// Out puts:
// B B
// And at the contrary:
class Cl {
 function Cl($a, $b) {
   echo("B ");
 }
 function Cl($a) {
   echo("A ");
 }
}
new Cl(1);
new Cl(1, 2);
// Out puts:
// Warning: Missing argument 2 for cl() ...


ianyates

Although not very good practice, I had a use for it.
In PHP you can destroy an object using unset(object instance) from outside of the object, but I needed to destroy the object from within.
After much experimentation, I simply set $this to null within a function inside the object.
This had the desired affect of removing the object from memory.
Note that unsetting $this does not have the same affect.
It would be better practice to set a variable within the object when it needed to be destroyed and then pick this up externally to mark the object as destroyed.
Hope this helps someone.


20-sep-2003 12:08

Adding to the last post...
If u DON'T WANT to override the parent creator just put
<?
// ...
   function On_Create() {
       parent::On_Create();
       // Some code
   }
//...
?>
It will calls the parent creator and u can extend how many classes do you even want to...


steffen staehle

A note on a constructor's return value:
When creating an instance of a class, 'new' obviously returns the object, not the constructor's return value (if any).
Still, it might be tempting to communicate the success or failure of constructing the object via a return value:
class A
{
  function A()
  {
      // ...
       // some error occurred
      return FALSE;  
  }
}
if ($a = new A())
{
  // success, use $a ...
}
THIS WILL NOT WORK the way intended.
'new' returns the object, the assignment returns the value of the assignment, i.e. the object, and whether an object evaluates as TRUE does not depend on the constructor's return value.
My preferred solution - set some object property during the construction phase that you can check against explicitely.


12-dec-2001 07:38

A couple of comments :
<<If a class has no constructor, the constructor of the base
class is being called, if it exists.>>
Actually the constructor of the base class is NOT called.
The child class inherits TWO copies of the father constructor,
one named after the father, one named after the child.
(other methods are also inherited by copy, as stated in the manual!)
The copied method named after the child is being called. For
most purposes this is the same, but beware of static variables.
class bar{
function bar($var = null){
static $methodname = "bar::bar";
if(isset($var)) $methodname = $var;
else echo "$methodname <b"."r>";
}
}
class foo extends bar{
function printMethods(){
bar::bar();
foo::bar();
foo::foo();
}
}
foo::printMethods(); // prints 3 bar::bar
foo::foo('foo::foo');
foo::bar('foo::bar');
foo::printMethods(); // prints bar::bar,foo::bar,foo::foo
$foo = new foo; // prints foo::foo
$bar = new bar; // prints bar::bar
Ivan


johan_php

/**
 * Example Class for getting around the problem with
 * overloaded functions constructors.
 *
 * This exapmple are asuming that you want to overload
 * the constructor Object() with different arguments.  
 */
class Object {
 /**
  * The real constuctor for this class.
  *
  * NOTE: Parlameter may not have the value null
  *       unless you changes the default value in
  *       the constructor.
  */
 function Object($param1 = null, $param2 = null) {
   $numargs = func_num_args();
   $arg_list = func_get_args();
   $args = "";
   for ($i = 0; $i < $numargs && $arg_list[$i] != null; $i++) {
     if ($i != 0) {
       $args .= ", ";
     }
     $args .= "\$param" . ($i + 1);
   }
   // Call constructor function
   eval("\$this->constructor" . $i . "(" . $args . ");");
 }
 /**
  * Functiorn that will be called if constructor is called
  * with no parlameter as agument.
  */
 function constructor0() {
   echo("Constructor 1: No parlameter." . "\n");
 }
 /**
  * Functiorn that will be called if constructor is called
  * with one parlameter as agument.
  */
 function constructor1($param) {
   echo("Constructor 2: \$param=" . $param . "\n");
 }
 /**
  * Functiorn that will be called if constructor is called
  * with two parlameter as agument.
  */
 function constructor2($param1, $param2) {
   echo("Constructor 3: \$param1=" . $param1 . "\n");
   echo("Constructor 3: \$param2=" . $param2 . "\n");
 }
}
new Object();
new Object("A String value");
new Object("Another String...", 1);
// Output:
Constructor 1: No parlameter.
Constructor 2: $param=A String value
Constructor 3: $param1=Another String...
Constructor 3: $param2=1


Change Language


Follow Navioo On Twitter
class
extends
Constructors
Scope Resolution Operator (::)
parent
Serializing objects - objects in sessions
The magic functions __sleep and __wakeup
References inside the constructor
Comparing objects
eXTReMe Tracker