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



PHP : Language Reference : Classes and Objects (PHP 5) : Constructors and Destructors

Constructors and Destructors

Constructor

PHP 5 allows developers to declare constructor methods for classes. Classes which have a constructor method call this method on each newly-created object, so it is suitable for any initialization that the object may need before it is used.

Note:

Parent constructors are not called implicitly if the child class defines a constructor. In order to run a parent constructor, a call to parent::__construct() within the child constructor is required.

Example 10.8. using new unified constructors

<?php
class BaseClass {
  function
__construct() {
      print
"In BaseClass constructor\n";
  }
}

class
SubClass extends BaseClass {
  function
__construct() {
     
parent::__construct();
      print
"In SubClass constructor\n";
  }
}

$obj = new BaseClass();
$obj = new SubClass();
?>


For backwards compatibility, if PHP 5 cannot find a __construct() function for a given class, it will search for the old-style constructor function, by the name of the class. Effectively, it means that the only case that would have compatibility issues is if the class had a method named __construct() which was used for different semantics.

Destructor

PHP 5 introduces a destructor concept similar to that of other object-oriented languages, such as C++. The destructor method will be called as soon as all references to a particular object are removed or when the object is explicitly destroyed or in any order in shutdown sequence.

Example 10.9. Destructor Example

<?php
class MyDestructableClass {
  function
__construct() {
      print
"In constructor\n";
     
$this->name = "MyDestructableClass";
  }

  function
__destruct() {
      print
"Destroying " . $this->name . "\n";
  }
}

$obj = new MyDestructableClass();
?>


Like constructors, parent destructors will not be called implicitly by the engine. In order to run a parent destructor, one would have to explicitly call parent::__destruct() in the destructor body.

Note:

Destructors called during the script shutdown have HTTP headers already sent. The working directory in the script shutdown phase can be different with some SAPIs (e.g. Apache).

Note:

Attempting to throw an exception from a destructor (called in the time of script termination) causes a fatal error.

Code Examples / Notes » language.oop5.decon

jcaplan

__construct and __destruct must be declared public in any class that you intend to instantiate with new.   However, in an abstract (or never-instantiated base) class you can declare them private or protected, and subclasses can still refer to them via parent::__construct (!) (tested in PHP 5.1.2).

timothyrhodes

You are receiving that error because you are calling a function outside of your class that requires the instantiated (object) variable "example" which doesn't exist until your class has been constructed into an object and assigned to "example. Here is the proper solution.
<?php
function foo($bar)
{
$bar->friend();
}
class example_class
{
function example_class()
{
foo($this);
}
function friend()
{
// Uhhh :)
}
}
$example = new example_class;
?>


theubaz

What you could do is write the constructor without any declared arguments, then iterate through the arguments given and check their types/values to determine what other function to use as the constructor.

kida

Well:
class A
{
    public function __construct()
    {
            //do something
    }
}
class B extends A
{
    protected function __construct()
    {
         parent::__construct();
    }
}
You can't make this becouse B::__construct() MUST have the same visibility or a weaker visibility of A::__construct() !!??!!
SO I THINK it's better
class A
{
    public function A()
    {
            //do something
    }
}
class B extends A
{
    protected function  B()
    {
         parent::A();
    }
}
Because it works. Instead of what they're saying ;)


yoops

Unfortunately, PHP doesn't implement C++-like stack based object.

24-feb-2005 09:08

To caliban at darklock dot com: Why not just define a dummy constructor <?PHP function __construct() {} ?> in the base class? This adds little overhead, and allows you to both extend the class worry-free and later add construct functionality to the base class.
And now, about destructors: I haven't seen this clarified anywhere in the manual, but object destructors are called implicitly at script shutdown for all objects that still exist at that Tpoint. his happens *after* any shutdown functions set with <?PHP register_shutdown_function() ?> have been called.
Objects appear to be destructed in the order they were defined, which means you have to be careful with destruct methods that rely on the functionality of other objects (e.g. on a database-handler) as they will have shut down already.


nayyar

This might help you understanding __construct() function.
<?
class submit
{
var $val1;
var $val2;
function __construct()
{
 $this->val1 = 7;
 $this->val2 = 9;
}
function sum()
{
return $this->val1 + $this->val2;
}


}
$tt = new submit;
$tt->val1 = 7;
$tt->val2 = 7;
$result = $tt->sum();
echo $result;
?>


soapthgr8

This is just to clarify that the Singleton pattern is a bit more complex than just making the constructor private. It also involves caching an instance of the object and always returning the cached value. So, in the previous example, the getNewInstance() function would undermine the intent of the Singleton pattern. Instead you would just need a getInstance() function, like so.
<?php
class A {
 // cached instance
 private static oInst = null;
 /**
   * Prevent an object from being constructed.
   */
 private function __construct( ) {}
 /**
  * Function to return the instance of this class.
  */
 public static function getInstance( ) {
   if (is_null(self::$oInst)) {
     self::$oInst = new A( );
   }
   return self::$oInst;
 }
}
?>


01-oct-2006 07:03

This is a simple thing to bear in mind but it's also easy to forget it.  When chaining object constructors and destructors, always remember to call the superclass __construct() method in the subclass __construct() so that all superclass members are properly initialized before you start initializing the ones belonging to your subclass.  
Also, you will usually want to do your own cleanup first in your subclass __destruct() method so you will probably want to call the superclass __destruct() as the last thing in your subclass so that you can use resources defined in the superclass during the cleanup phase.
For example, if your superclass includes a database connection and your subclass __destruct method commits things to the database then if you call the superclass destruct before doing so then the database connection will no longer be valid and you will be unable to commit your changes.


peter molnar

There were many notes about the inability of defining multiple constructors for the class.
My solution is to define separate static methods for each type of constructor.
<?php
class Vector {
   private $x;
   private $y;
   public function __construct() {
       $this->x = 0;
       $this->y = 0;
   }
   public static function createXY($x, $y) {
       $v = new Vector();
       $v->x = $x;
       $v->y = $y;
       return $v;
   }
}
?>


frederic dot barboteu

The manual says:
"Like constructors, parent destructors will not be called implicitly by the engine."
This is true ONLY when a __destruct() function has been defined by the child class.
If no __destruct() function exists in the child class, the parent's one will be implicitly executed.
So be carefull if you have some ancestor executing a particular task in its __destruct() function, an you plan its childs to execute it or not, wether you include "parent::__destruct()" or not.
If you want the child not to execute its parent __destruct() function, you must ensure that it has its own __destruct() function, even if empty. Then the parent's one will not be executed.
This can be verified with the following code:
<?php
#
class AncestorClass {
function __destruct() {
echo '<br />AncestorClass: destructing '.get_class($this);
}
}
#
class ParentDestructClass extends AncestorClass {
function __destruct() {
echo 'ParentDestructClass: destructing itself';
parent::__destruct();
}
}
#
class EmptyDestructClass extends AncestorClass {
function __destruct() {
echo 'EmptyDestructClass: destructing itself';
}
}
#
class NoDestructClass extends AncestorClass {
}
#---
echo '<hr>';
$p=new ParentDestructClass();
unset($p);
echo '<hr>';
$e=new EmptyDestructClass();
unset($e);
echo '<hr>';
$n=new NoDestructClass();
unset($n);
echo '<hr>';
?>
which displays:
---
ParentDestructClass: destructing itself
AncestorClass: destructing ParentDestructClass
---
EmptyDestructClass: destructing itself
---
AncestorClass: destructing NoDestructClass
---


peter molnar

The manual says: "Destructor is called during the script shutdown so headers are always already sent."
This is obviously not true. If you instantiate a class in a function or class method, but it is not returned by the method, nor is it saved in a global or object member variable, the object is cleaned up, and it's destructor is called. This can of course occur before anything is printed or sent to the client.


fredrik

The fact that class names are case-insensitive in PHP5 also applies to constructors. Make sure you don't have any functions named like the class *at all*.
This has bitten me a few times.
<?php
class Example extends Base
{
 function example()
 {
   echo "This gets called";
 }
}
class Base
{
 function __construct()
 {
   echo "Not this";
 }
}
?>


dave

phaxius:
Why not just use this:
<?php
// ...
public function __construct()
{
 $this->Args = func_get_args();
}
// ...
?>


reza mahjourian

Peter has suggested using static methods to compensate for unavailability of multiple constructors in PHP.  This works fine for most purposes, but if you have a class hierarchy and want to delegate parts of initialization to the parent class, you can no longer use this scheme.  It is because unlike constructors, in a static method you need to do the instantiation yourself.  So if you call the parent static method, you will get an object of parent type which you can't continue to initialize with derived class fields.
Imagine you have an Employee class and a derived HourlyEmployee class and you want to be able to construct these objects out of some XML input too.
<?php
class Employee {
  public function __construct($inName) {
      $this->name = $inName;
  }
  public static function constructFromDom($inDom)
  {
      $name = $inDom->name;
      return new Employee($name);
  }
  private $name;
}
class HourlyEmployee extends Employee {
  public function __construct($inName, $inHourlyRate) {
      parent::__construct($inName);
      $this->hourlyRate = $inHourlyRate;
  }
  public static function constructFromDom($inDom)
  {
      // can't call parent::constructFromDom($inDom)
      // need to do all the work here again
      $name = $inDom->name;  // increased coupling
      $hourlyRate = $inDom->hourlyrate;
      return new EmployeeHourly($name, $hourlyRate);
  }
  private $hourlyRate;
}
?>
The only solution is to merge the two constructors in one by adding an optional $inDom parameter to every constructor.


contact

Note that php5 use in priority __construct() instead of [classname](). So you could build a constructed/destructed class for php4/5 very easily using this.
<?
class test {
function test() {
 $this->__construct();
 register_shutdown_function(array($this,"__destruct"));
}
function __construct() {
 echo "construct\n";
}
function __destruct() {
 echo "destruct\n";
}
};
$t=new test();
?>
In case you use unset($t) in php4, the destructor is not called. so be careful.


chanibal

Note that if a class contains another class, the contained class's destructor will be triggered after the destructor of the containing class.
<?php
class contained {

protected $parent;
public function __construct(&$p) {
 # $this->parent=&$p;
 }

public function __destruct() {
 /* unset $this->parent */
 print 'contained ';
 }
}

class containing {
protected $contained;
public function __construct() {
 $this->contained=new contained($this);
 }
public function __destruct() {
 // unset($this->contained);
 print 'containing ';
 }
}


new containing();
?>
Will output
containing contained
After uncommenting the // comment, the output will change to
contained containing
Adding a reference from the contained class to the containing one (the # comment) will not change that, but beware, because it can cause random errors in other destructors in the parts of the script which seem unrelated! (PHP Version 5.1.2)


magus do t xion a t g mail d ot c o m

Looking through the notes I noticed a few people expressing concern that PHP5 does not support multiple constructors...
Here is an example of a method that I use which seems to work fine:
class Example
{
    function __construct()
    {
          echo "do some basic stuff here";
    }
    function Example($arg)
    {
          echo $arg;
    }
}
You then can call with or without arguments without having notices and/or warnings thrown at you... Of course this is limited but if you don't need something complex this can help to get the job done in some situations.  I believe you could also add arguments to the __construct() function and as long as it is different than Example() 's args you would be fine. Although I have yet to test this.


webmaster

Just a note on the __construct() function (in my example it's the classname but it has the same effect).  When you try call a function outside the class, wich calls a function wich is inside the class in construction you will get a "Call to function on undefined object" error. The first piece of code shows a failing script. The seccond piece of code shows a work-around solution .
Examples:
The wrong code:
<?php
function foo($bar)
{
global $example;
$example->friend();
}
class example_class
{
function example_class()
{
foo('bar');
}

function friend()
{
// Uhhh :)
}
}
$example = new example_class;
?>
The working code:
<?php
function foo($bar)
{
global $example;
$example->friend();
}
class example_class
{
function example_class()
{
// Some other code
}

function example_class_step2()
{
foo('bar');
}

function friend()
{
// Uhhh :)
}
}
$example = new example_class;
$example->example_class_step2();
?>


php dot net

It looks like `echo()`ed output from the __destructor() function is displayed onto screen _before_ other output that the class may have have already sent before.
This can be misleading if you have debug info printed in the destructor but not a problem if you know it.


miguel dot simoes

In the PHP documentation example you can change the class name under $this->name = "ClassName" with $this->name = __CLASS__;
This way you'll have a starting point for having a dinamic content even inside PHP code and providing a good base for having a "Class template" with __construct and __destruct.


robert

In response to prauscher at gmx dot net:
As tcknetwork wrote earlier, if you try to access a file from a destructor, you have to be aware that you are probably in the webservers root directory, because the destructor already "forgot" what you working directory was. If you try to write a file there, you will probably have no permission to do so.
Read tcknetwork's post for a solution.


laurenty

In response to jonas at widarsson dot com
You should use default argument values such as:
<?php
  class myclass{
      function __construct($str = 'default'){
          $this->a = $str;
      }
      function say(){
          echo $this->a;
      }
  }
 ?>


09-nov-2006 11:32

In response to Dave:
Because this method of working (__construct) saves typing and complexity.


obeliks

In reply to "luancarvalho at terra dot com dot br":
You can also use an constructor without parameters and get the parameters via func_get_args();
Then you can check if it is_int or is_whatever, and process it accordingly.


shakeel

In order to make constructor overloading in PHP5, we have to make a function __construct and inside from that's constructor, use func_num_args to get the total numbers of arguments supplied to the constructor and then do appropriate work or call some other function. The value of any argument can be acceessed by using
func_get_arg($index) function. This is illustrated in the
following Example.
<?php
class Overload
{
private $var1;
private $var2;
# constructor which acts as a overloaded constructors
public function __construct()
{
$num_args=func_num_args();
switch ($num_args)
{

case '0':
       // Do something
       # set zero in both instance variables. if no argument is
       #supplied
     $this->var1 = $this->var2 =0;
     break;
case '1':
      # get value of the argument
$arg1=func_get_arg(0);
       // Do something else;
       /* asigned ist arg. to ist instance variable and Zero in the 2nd instance variable or any other initializing value. because only one argument is supplid. */      
$this->var1 = $arg1;
$this->var2 = 0;
break;
case '2':
// get value of both arguments
$arg1=func_get_arg(0);
$arg2=func_get_arg(1);
// Do something else;

$this->var1 = $arg1;
$this->var2 = $arg2;
break;
} // end of switch statement
 
} // end of function __construct

// function to display the values of instance variables
function display()
{
echo "var1: $this->var1
";
echo "var2: $this->var2
";
}// end of function display
}// end of class
// create 3 objects with different no. of arguments
$over = new Overload();
$over1 = new Overload(5);
$over2 = new Overload(5,10);
// call display function with all 3 objects.
$over->display();
$over1->display();
$over2->display();
?>
output:
var1: 0
var2: 0
var1: 5
var2: 0
var1: 5
var2: 10


admin @t ifyouwantblood comma de

in addition to frederic dot barboteu at laposte dot net note
not only parent destructors are called if the child class does not specify a destructor, this also applies to constructors.
so if you don't want the parent constructor or destructor called, you will have to make sure the child has its own constructor or destructor, even if theyre empty.


stanley dot turnteen

IMHO using func_get_args() is superior to constructor polymorphism, because you don't have to define constructors for every possible way a class can be initialized.
The pattern I use looks like this;  all you have to do is pass the parameters in the correct order.
<?php
 class Movie
 {
   public $title;
   public $director;
   public $stars;
   public $year_released;
   
   public function __construct()
   {
     $args = func_get_args();
     
     foreach(array("title", "director", "stars", "year_released") as $i)
     {
       if(empty($args))
       {
         break;
       }
       
       $this->$i = array_shift($args);
     }
   }
   
 }
?>


dominics

If you're using E_STRICT error reporting, PHP will tell you if you define both __construct() and an old-style constructor (a function with the same name as the class) together in a class. Note that this occurs even if the old constructor function is abstract or final (for instance, if you were intending to only use it in a sub-class). Be wary of this if you're trying to implement the 'command' design pattern.
The solution? Either turn E_STRICT off (and possibly forgo some other important notices), rename your function (and possibly make things a little more complicated), or look at using an interface.


derk

If a constructor is not present in a child class, php5 will try to call a constructor from the parent class. This behaviour can be used to somewhat simulate constructor chaining.
<?php
abstract class Parent {
   function __construct()
   {
       echo "Parent constructor called\n";
       $this->myConstruct();
   }
}
class Child extends Parent {
   function myConstruct()
   {
       echo " Child 'contructor' called";
   }
}
$c = new Child();
?>
will output:
Parent constructor called
Child 'constructor' called


randallgirard

I've been working on a project for a while now, and for example in my DB handler I wanted to load var's to the objects late; However, without doing it manually on the object itself but through a single static call. For other reasons, in my Sessions I then wanted to end them early without registering a shutdown routine for every possible session. Hence, I needed a way to track EVERY instance or object of the class.
(Of course in a normal website design, this would be overly coded. It's more of a framework for a CMS, Daemon service, anything I wanna create etc...)
<?php
class example {
public static $OBJS = array();
public $id;

public function __construct() {
example::$OBJS[] = $this;
# I actually use a 'lastKey' routine here, but in this example the following should work:
$this->id = key( array_slice(example::$OBJS, count(example::$OBJS) -1, 1, true) );
}

public function __destruct() {
$this->close();
}

# unset the tracked object
private function destruct() {
if ( isset(example::$OBJS[$this->id]) )
unset(example::$OBJS[$this->id]);
}

# public shutdown routine
public function close() {
if ( isset($this->destructed) )
return;
# ...
$this->destruct();
$this->destructed = true;
}

}
?>
You could then also use register_shutdown_function(...) to call a static class method, which loops through ALL the objects and calls the $obj->close routine.
<?php
# register a shutdown function which triggers before destructors (hence when such results are desired for a Session class, etc)
register_shutdown_function("example::destructors");

class example {

# ... see above code example

# static class method to destruct all objects
public static function destructors() {
foreach ( example::$OBJS as $obj )
$obj->destruct();
}

}
This will probably give some people new ideas, and other will probably be confused. Happy coding...
NOTE: I didn't test the code(s) above. They were a rewritten example from my frameworks.
?>


prauscher

I saw no note in the manual about my function. If you want to write a file in a __destruct - function, it will fail with a "Permission denied" Error.

james laver

I recently found, while implementing a database backed session class, that PHP has an apparently less than desirably structured destruction order. Basically, my session class which would have saved when destructed, was being destructed after one of the classes it depends on. Apparently we cannot, therefore depend on PHP to use reverse initialisation order.
My solution was to use register_shutdown_function, which is called before any objects are killed on script end.
Quick example (if you're going to use it, I recommend tidying up the code somewhat) :
<?php
class Session
 function __construct()
 {
   //Initialise the session here...
   
   //Register the shutdown function
   register_shutdown_function(array($this,"save"));
 }
 function save()
 {
   //Save it here
 }
 function __destruct()
 {
   //Persisting the session here will not work.
 }
?>


lenix

i just found out that, together with the 'final' keyword, it gets pretty easy to write a parent-class with a constructor always called and not overwriteable by any childs extending that class.
<?php
  abstract class Foo {
     final function __construct( $Bar ) {
        echo "Foo::__construct( $Bar );<br />\n";
     }  
  }
  class Baz extends Foo {
     public function printBaz( $Val = "" ) {
        echo "Baz::printBaz( $Val );<br />\n";
     }
  }
 
  try {
     $Obj =& new Baz( "Passed to new Baz( )" );
     $Obj->printBaz( "method of Baz" );
  } catch ( Exception $E ) {
     echo 'Caught exception: ',  $E->getMessage(), "<\n";
  }
?>
of course subclasses are forced that way to have no contructor on their own.


prieler

i have written a quick example about the order of destructors and shutdown functions in php 5.2.1:
<?php
class destruction {
var $name;
function destruction($name) {
$this->name = $name;
register_shutdown_function(array(&$this, "shutdown"));
}
function shutdown() {
echo 'shutdown: '.$this->name."\n";
}
function __destruct() {
echo 'destruct: '.$this->name."\n";
}
}
$a = new destruction('a: global 1');
function test() {
$b = new destruction('b: func 1');
$c = new destruction('c: func 2');
}
test();
$d = new destruction('d: global 2');
?>
this will output:
shutdown: a: global 1
shutdown: b: func 1
shutdown: c: func 2
shutdown: d: global 2
destruct: b: func 1
destruct: c: func 2
destruct: d: global 2
destruct: a: global 1
conclusions:
destructors are always called on script end.
destructors are called in order of their "context": first functions, then global objects
objects in function context are deleted in order as they are set (older objects first).
objects in global context are deleted in reverse order (older objects last)
shutdown functions are called before the destructors.
shutdown functions are called in there "register" order. ;)
regards, J


donpro

I am using PHP 5.0.3 and was playing with the above example.  I changed the code by omitting the 'final' keword from the contructor in the Foo class and still got the same result, i.e., the constructor was called when only this code was run:
$Obj = new Baz( "Passed to new Baz( )" );


jonas

I am porting a little parser from C++ to PHP and came across that PHP (5.1.6-pl6-gentoo) does not support multiple constructors.
<?php
  class myclass{
  var $a = 'unset';
  function __construct(){
  $this->a = 'default';
  }
  function __construct($str){
  $this->a = $str;
  }
  function say(){
  echo $this->a;
  }
  }
 
  $a = new myclass();
  $a->say();
  echo "<br/>";
  $a = new myclass("test");
  $a->say();
 ?>
If you run that, you would get:
Fatal error: Cannot redeclare myclass::__construct()
I guess one could fallback to passing an array to the constructor and inside the constructor determine what to make of that array, and so in a workaroundish way have multiple constructors all in one constructor.


typer85

I am not sure if the following is known or not, but here goes.
I am sure most are aware of the concept of making a Class Constructor private to prevent an Object of that Class from being created as follows:
<?php
class A
{
   /**
    * Prevent An Object From Being Constructed.
    */
   private function __construct( ) {
       
   }
}
?>
In some code, if I try to do the following:
<?php
$Obj = new A( );
?>
PHP will fail with a fatal error. This is useful when creating Classes that are composed of only static functions or in a more advanced example, when applying the Singleton Pattern to a Class design.
However what is not properly documented in this manual but is pretty simple to note, especially if you read the notes regarding the Singleton Pattern, is that you can create an Object of a Class that has a private Constructor from within the Class itself.
Confused ... so am I, so allow me to provide a visual example as follows:
<?php
class A
{
   /**
    * Prevent An Object From Being Constructed.
    */
   private function __construct( ) {
       
   }
   /**
    * Function To Return An Instance Of This Class.
    */
   public static function getNewInstance( ) {
       
       return new A( );
   }
}
?>
In some code, if I try to do the following:
<?php
$Obj = A::getNewInstance( );
?>
PHP in this case will not fail with a fatal error and instead the variable '$Obj' becomes an Object with an instance of Class 'A'.
This is a simple example and pretty advanced things can be done using this method. I am sure advanced developers are aware of this so this is just a little note going out to new PHP developers.


jonas

Hello.
Here we go again. Delete my old entry if you wish.
Trying to port a parser from C++ to PHP I came across that PHP doesn't support multiple constructors. I believe PHP lacks the possibility to create new objects out of different types of information without writing specialized functions.
An example, which does not work:
<?php
class DocNode{
  function __construct(DocNode $copyfrom, DocNode $parent = null, DocNode $insertAfter = null){ /* ... */}
  function __construct($type = 'text', $collapsable = false){ /* ... */}
}
?>
If you run that, you would get:
Fatal error: Cannot redeclare DocNode::__construct()
I guess one could fallback to passing an array to the constructor and inside the constructor determine what to make of that array, and so in a workaroundish way have multiple constructors all in one constructor.


phaxius

Hello, I've been messing with php for about a week but am learning a lot.  It occurred to me that it might be necessary in some cases to write a class that takes a variable number of arguments.  After some experimentation, this example was formed:
class variableArgs{
public $a = array();
protected $numOfArgs;
public function __construct()
{
 $numOfArgs=func_num_args();
 if(func_num_args()==0)
 {
   $numOfArgs=1;
   $a[0]='No arguments passed';
   $this->Arg[0]=$a[0];
 }
 else
 for($i=0; $i<func_num_args(); $i++)
 {
   $a[$i]=func_get_arg($i);
   $this->Arg[$i]=$a[$i];
 }
}
public function showArgs()
{
 echo 'showArgs() called <br />';
 for ($i=0; $i<$numOfArgs; $i++)
 {
   echo '$i: ' . $i . '<br />';
   echo $this->Arg[$i];
echo '<br />';
 }
}
public function __destruct(){}
}
$test1 = new variableArgs;
$test2 = new variableArgs("arg1");
$test3 = new variableArgs("arg1", "arg2");
$test4 = new variableArgs("arg1", "arg2", "arg3");
$test1->showArgs();
$test2->showArgs();
$test3->showArgs();
$test4->showArgs();
This outputs the following:
showArgs() called
$i: 0
No arguments passed
showArgs() called
$i: 0
arg1
showArgs() called
$i: 0
arg1
$i: 1
arg2
showArgs() called
$i: 0
arg1
$i: 1
arg2
$i: 2
arg3
I have no idea how efficient this is, but it works at any rate.  Hopefully this helps someone.


aya

For those who aren't already aware, PHP5 currently suffers from the classic reference counting leak. See http://en.wikipedia.org/wiki/Reference_counting for more info.
Example code:
<?php
   class Noisy
   {
       private $name;
       public function __construct($name)
       {
           $this->name = $name;
           echo "Noisy::__construct($this->name)\n";
       }
       public function __destruct()
       {
           echo "Noisy::__destruct($this->name)\n";
       }
   }
           
   function foo($num)
   {
       $noisy = new Noisy($num);
       //$noisy->me = $noisy; // Uncomment this line to create a cyclic reference
   }
   for ($i = 0; $i < 10; ++$i)
       foo($i);
?>
As it stands, the destructor of class 'Noisy' will be called on '$noisy' when it goes out of scope in function 'foo', but uncommenting the second line in function 'foo' will prevent this, and cause a memory leak.
See http://bugs.php.net/bug.php?id=33595 for a bug report, which reads as if this is not likely to get fixed in the near future, so watch out!


luancarvalho

Even PHP 5 doesn't allow to redeclare a method in a class. So, it's impossible to create differents constructors to a object with unique parameters, something common JAVA.
To overcome this limitation I've been forced to use something like this:
<?php
class MyClass {
 public $n1;
 public $n2;
 function MyClass ($n1 = FALSE, $n2 = FALSE) {
   if ($n1) {
     $this->n1 = $n1;
   } else {
     $this->n1 = 0;
   }
   if ($n2) {
     $this->n2 = $n2;
   } else {
     $this->n2 = mt_rand();
   }
 }
}
?>


rocco

Before PHP reaches the point where it calls the __destruct functions, it has already done a session_write_close() so you can no longer write anything to the session.
I wanted it to copy some variables from my class into the session once the script had finished but now having to get the last function to call a SaveToSession() function.
In php versions 5.0.2 and 5.0.4


contact

be careful while trying to access files with __destruct() because the base directory (getcwd()) will be the root of your server and not the path of your script, so add before all your path called in __destruct() :
EITHER   dirname($_SERVER["SCRIPT_FILENAME"])."my/path/"
OR      dirname(__FILE__)."my/path/"
        (be careful with includes, it will give the path of the file processed and not the main file)


ckoschmied

Be aware of the fact that if you create a new instance of a class like this:
$instance = new Class();
$instance will not contain a valid reference to the newly created object until the constructor is finished. So don't use $instance while the constructor is still running.
Well, on the other side, why would you want to do it? I wanted to, and it took me some hours to figure out.
Even though it's quite obvious if you think about it :-)


jochem

at: derk AT oneindig DOT com
You can achieve identical functionality by doing this:
<?php
class Parent {
  function __construct()
  {
      echo "Parent constructor called\\n";
  }
}
class Child extends Parent {
  function __construct()
  {
      parent::__construct();
      echo " Child 'contructor' called";
  }
}
$c = new Child();
?>
Added advantage is that Parent doesn't need to have the method myConstruct(), and that you're using constructors like they were intended.


apfelsaft

at the end of a script all remaining objects aren't in fact destructed. it is only their __destruct() method, which will be called. the objects still exist after that.
so, if your database connection object has no __destruct() or at least it doesn't disconnects the database, it will still work.
in general, there is no need to disconnect the database (especially for persistent connections).


developit

as [kida at keymail dot it] said you can't weaken a visibility of constructor when extending some class. but suggested trick that uses both old and new constructor namimg syntaxes to weaken visibility from 'protected' to 'public' seems a little bit odd. allthough it works allright. declaring extended class as 'abstract' with 'public' constructor will do quite the same thing in a more elegant manner and without any syntax mess.
<?php
class A
{
 public function __construct()
 {
   //do smth
 }
}
abstract class B extends A
{
 public function __construct()
 {
   parent::__construct();
 }
}
?>
thus, you avoid instanciating class B as if it had a protected contructor


maniac_warlord

as reported in bug 34206 the working dir is changed to the server root
the best workaround is
<?php
class Foo
{
   public function bar()
   {
           $this->_cwd = getcwd();
   }
   public function __destruct()
   {
       chdir($this->_cwd);
   }
}
?>
Be aware the booty trap!
http://bugs.php.net/bug.php?id=34206


stanley dot turnteen

Actually a buddy just pointed out a more elegant method:
<?php
 class Movie
 {
   public $title;
   public $director;
   public $stars;
   public $year_released;
   
   public function __construct()
   {  
     @list($this->title,
          $this->director,
          $this->stars,
          $this->year_released) = func_get_args();
   }
   
 }
?>


caliban

(Referring to the earlier example code and comment)
The "final" keyword forbids the Baz object to define its own constructor; defining an override for a "final" method creates a fatal error. Without the "final" keyword, if the Baz object defines a constructor, the Foo constructor will not be called automatically; instead, the Baz constructor will be called and the Foo constructor will not.
If the Foo constructor SHOULD be called, e.g. to open files or initialise member variables, Baz will need to call parent::__construct() explicitly. In most cases, this is what you will want to do when extending a class, but you can't just do it as a matter of habit... because if Foo does not HAVE a constructor, parent::__construct() is a fatal error. This creates a problem. (The problem can be easily solved with @parent::__construct(), if you don't care about OTHER errors that might arise.)
So given an object Foo with no constructor, any extension objects MUST NOT call parent::__construct() in their own constructors. If Foo later *adds* a constructor, the extension objects SHOULD call parent::__construct() if they have constructors themselves. (If they don't, Foo's constructor will be called automatically.) A whole slew of problems pop up as a result, so what we need is a way to say "call the parent class constructor if there is one".
An immediate avenue presents itself with is_callable(array("parent","__construct")), but this isn't as useful as you might expect because it doesn't handle old-style constructors. Basically, if Foo has a constructor named Foo(), parent::__construct() will call parent::Foo(), but is_callable(array("parent","__construct")) returns FALSE.
Fortunately, this is easily resolved with a call to is_callable(array("parent",get_parent_class($this))). Adding that bit of code into the constructor of your derived classes will achieve exactly what we want, namely to call the parent's constructor if there is one.
But there always seems to be a catch... this only works one level down. If Baz extends Bar extends Foo, this code will get Baz to call Bar's constructor, but Bar can't call Foo's constructor with it -- because $this is an instance of Baz, not Bar, so Bar cannot determine its parent class name correctly. (It is noteworthy that if Bar does not *have* a constructor, Baz will still happily pass a request through to Foo's constructor.) The reflection interface is the most obvious way to go about fixing this, but that gets a little too complex to be called a "note".


09-feb-2006 06:55

(Refering to: caliban at darklock dot com)
To force a constructor always to be called, and still be able to define a constructor on a derived class use the model below. Ideal for module architectures, because you only have to know the file and classname to construct an object.
<?php
class Parameter {}
abstract class BaseClass
{
protected $param;

public final function __construct( Parameter $param )
{
$this->param = $param;
$this->pseudoConstruct();
}

protected abstract function pseudoConstruct();
}
class ConcreteClass extends BaseClass
{
protected function pseudoConstruct()
{
echo __CLASS__.' constructor';
}
}
$refl = new ReflectionClass( 'ConcreteClass' );
if( !$refl->isSubclassOf( 'BaseClass' ) ) throw new Exception( 'Invalid base class!' );
$refl->newInstance( new Parameter() );
?>


04-mar-2005 11:48

> To caliban at darklock dot com: Why not just define
> a dummy constructor
Because you don't always get to modify your base classes. Once you get beyond the "build to suit" range of software development, you end up having to work with other people's code, and sometimes you just plain can't change it. When Bob is in charge of making changes to that object, you can't add a dummy constructor. You have to tell Bob to do it, and until Bob does it, you don't get it. So if you want to hit your deadlines, you don't count on Bob caring enough about your job to make the changes you want... you work around it. It might be convenient for *you* to have a constructor on that object, but when you're only one of several thousand people that are using it, your convenience isn't generally among the design criteria.
Smaller projects where you can add whatever you want wherever you want will not have this problem, in which case the dummy constructor is indeed a better solution.


Change Language


Follow Navioo On Twitter
Introduction
The Basics
Autoloading Objects
Constructors and Destructors
Visibility
Scope Resolution Operator (::)
Static Keyword
Class Constants
Class Abstraction
Object Interfaces
Overloading
Object Iteration
Patterns
Magic Methods
Final Keyword
Object cloning
Comparing objects
Reflection
Type Hinting
Late Static Bindings
eXTReMe Tracker