search for in the  
<Autoloading ObjectsVisibility>
Last updated: Thu, 19 May 2005

Constructors and Destructors

Constructor

void __construct ( [mixed args [, ...]] )

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 19-6. 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

void __destruct ( void )

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.

Example 19-7. 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: Destructor is called during the script shutdown so headers are always already sent.



User Contributed Notes
Constructors and Destructors
rocco at bluora dot com dot au
16-Apr-2005 11:29
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 at tcknetwork dot com
15-Apr-2005 11:45
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.
apfelsaft
30-Mar-2005 04:59
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).
miguel dot simoes at newnet dot com dot pt
23-Mar-2005 07:01
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.
04-Mar-2005 06: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.
24-Feb-2005 04: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.
caliban at darklock dot com
22-Feb-2005 05:00
(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".
donpro at lclnav dot com
07-Jan-2005 09:52
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( )" );
lenix
27-Nov-2004 11:38
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.

<Autoloading ObjectsVisibility>
 Last updated: Thu, 19 May 2005
Copyright © 2001-2005 The PHP Group
All rights reserved.
This unofficial mirror is operated at: The Server Pages
Last updated: Thu May 19 18:35:34 2005 EDT