PHP
downloads | documentation | faq | getting help | mailing lists | wiki | reporting bugs | php.net sites | links | conferences | my php.net

search for in the

Operador de Resolución de Contexto (::)> <extends
Last updated: Fri, 22 Aug 2008

view this page in

Constructores

Los constructores son funciones en una clase que son llamadas automáticamente cuando se crea una nueva instancia de una clase con new. Una función se convierte en constructor cuando tiene el mismo nombre que la clase. Si una clase no tiene constructor, el constructor de la clase base será llamado, si existe.

<?php
class Auto_Carrito extends Carrito {
    function 
Auto_Carrito() {
        
$this->agregar_item("10"1);
    }
}
?>

Esto define una clase Auto_Carrito que es un Carrito más un constructor que inicializa el carrito con un item del número de artículo "10" cada vez que un nuevo Auto_Carrito se crea con "new". Los constructores pueden recibir argumentos y tales argumentos pueden ser opcionales, lo que los hace mucho más útiles. Para poder usar aun la clase sin parámetros, todos los parámetros deben ser opcionales, al proveer valores predeterminados.

<?php
class Constructor_Carrito extends Carrito {
    function 
Constructor_Carrito($item "10"$num 1) {
        
$this->agregar_item ($item$num);
    }
}

// Comprar lo mismo de antes.
$carrito_predeterminado = new Constructor_Carrito;

// Comprar esta vez en serio...
$carrito_diferente = new Constructor_Carrito("20"17);
?>

También puede usar el operador @ para callar los errores que ocurren en el constructor, p.ej. @new.

<?php
class A
{
    function 
A()
    {
        echo 
"Soy el constructor de A.<br />\n";
    }

    function 
B()
    {
        echo 
"Soy una función regular llamada B en la clase A.<br />\n";
        echo 
"No soy un constructor en A.<br />\n";
    }
}

class 
extends A
{
}

// Esto llama a B() como un constructor
$b = new B;
?>

La función B() en la clase A se convertirá de repente en un constructor en la clase B, aun cuando nunca fue esa la intención. A PHP 4 no le importa si la función está siendo definida en la clase B, o si ha sido heredada.

Caution

PHP 4 no llama constructores de la clase base automáticamente desde un constructor de una clase derivada. Es su responsabilidad propagar la llamada a constructores más arriba en la jerarquía cuando sea apropiado.

Los destructores son funciones que son llamadas automáticamente cuando un objeto es destruido, ya sea con unset() o simplemente al finalizarse su contexto. No hay destructores en PHP. Es posible usar register_shutdown_function() en su lugar para simular la mayoría de efectos de los destructores.



Operador de Resolución de Contexto (::)> <extends
Last updated: Fri, 22 Aug 2008
 
add a note add a note User Contributed Notes
Constructores
anthop at light-within dot org
04-Jan-2008 08:01
@ alexey:

My background has also been in more strongly-typed, object oriented languages like Java and C#, so learning PHP has been extremely frustrating at times.  Sometimes it feels like PHP is completely the wrong tool for the job (like using a chainsaw to perform brain surgery).

The phenomenon you're describing, I think, is a part of a larger difference in how PHP treats the $this variable.  It's defined as the first instance of an object it comes across.  PHP(4) is really a scripting, functional language so when the child was calling it's parent's constructor in your example, it wasn't really call a constructor, but simply just another function.  In fact, the two classes don't even have to be related:

<?php

class test_class_1 {
  var
$v;
 
  function
printV1() {
    echo
$this->$v, "<br />";
  }

}

class
test_class_2 {
  var
$v;
 
  function
printV2() {
   
test_class_1::printV1();
  }
 
}

$c1 = new test_class_1();
$c2 = new test_class_2();

$c1->$v = 1;
$c2->$v = 2;

test_class_1::printV1();
$c1->printV1();
$c2->printV2();

?>
The output of this should be:

1
2

The first empty line break is due to the printV1 function being called statically, and thus the $this-$v is undefined (though the line break still printed).

The "1" that was printed is from a straight-forward function call.

For the "2" that was printed, notice that the printV2 function correctly printed $c2's $v value, even though it was calling printV1.  test_class_1 isn't even the parent of test_class_2.  The $this variable just happened to point to the instance of test_class_2, and test_class_2 just happened to have a defined $v variable.

One way to think of it is that all functions are basically just functions and that classes are really just a way to help scope them.
alexey at gmail dot com
27-Nov-2007 03:15
Being a mostly C/C++ developer, I was suprised how PHP handles inheritance - quite differently. Imagine a child class that inherits from a parent. Typically, a child’s constructor invokes parent’s one according to the hierarchy. The interesting observation is that if parent invokes a method, that call goes to the child under construction!

Here is an example code:

class test_parent {
function test_parent() {
$this->func();
}

function func() {
echo “func_parent\n”;
}
}

class test_child extends test_parent {
function test_child() {
test_parent::test_parent();
}

function func() {
echo “func_child\n”;
}
}

$tmp = new test_child();

?>

The output is func_child which is the result of test_parent invoking func(). Here is an equivalent C++ code.

#include

class test_parent {
public:
test_parent() {
this->func();
}

void func() {
printf(”func_parent\n”);
}
};

class test_child: test_parent {
public:
test_child() {
}
void func() {
printf(”func_child\n”);
}
};

int main() {
class test_child *t;

t=new test_child();
return 0;
}

It prints out func_parent as the child is not available at the time when parent initializes itself.
mbrown at fensystems dot co dot uk
29-Sep-2007 07:44
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....   
    }
}
?>
sarjanwebdev at gmail dot com
17-Jul-2007 08:40
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"
dexen at NOSPAM dot example dot com
18-Jan-2006 12:44
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.
mark at dreamjunky dot com
29-Jun-2005 07:57
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
  }
}
jfonseca at matarese dot com
19-May-2005 05:07
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
phpnotes at ionws dot com
05-Apr-2005 08:51
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()
?>
herojoker at nexgo dot de
28-Feb-2005 05:28
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
john dot q dot webmaster at gmail dot com
25-Jan-2005 03:55
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 AT email DOT cz
03-Sep-2004 12:43
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
23-Jun-2004 01: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
31-Mar-2004 05: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.
    }

}
steffen-staehle at NO dot SPAM dot gmx dot de
01-Dec-2003 07:07
[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<p>";

   }
// constructor

} // TestBool

if ($obj = new TestBool1())
   echo
'obj is valid<p>';
else
   echo
'obj is invalid<p>';

class
TestBool2
{
   function
TestBool2($somevar)
   {
      echo
"2 somevar is: $somevar<p>";

   }
// constructor

} // TestBool

if ($obj = new TestBool2('hello world'))
   echo
'obj is valid<p>';
else
   echo
'obj is invalid<p>';

?>

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<p>";
     
// assume error
     
$this = NULL;

   }
// constructor

} // TestBool

if (($obj = new TestBool3('hello world')) !== NULL)
   echo
'obj is valid<p>';
else
   echo
'obj is invalid<p>';
?>

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).
20-Sep-2003 02: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...
pigmeu at pigmeu dot net
20-Sep-2003 01:30
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?
markus at emedia-solutions-wolf dot de
16-Sep-2003 01:00
Setting $this to null isn't available in PHP 4.3.3R3 anymore. Maybe in version below also.
johan_php at popbandetleif dot cjb dot net
06-Apr-2003 03:31
/**
  * 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
johan_php at popbandetleif dot cjb dot net
03-Apr-2003 11:39
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() ...
ogarbe at tf1 dot fr
01-Apr-2003 10:01
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 ...
}
steffen staehle
17-Jan-2003 06:11
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.
ianyates at yahoo dot com
14-Jan-2003 07:32
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.
dmarsh dot NO dot SPAM dot PLEASE at spscc dot ctc dot edu
18-Sep-2002 09:40
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
  }

}
eric+nospam at ypass dot net
04-May-2002 11:59
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
12-Dec-2001 09: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

Operador de Resolución de Contexto (::)> <extends
Last updated: Fri, 22 Aug 2008
 
 
show source | credits | sitemap | contact | advertising | mirror sites