28

Is there a reason why Magento has a _construct and a __construct method? Why does the additional _construct exist? Could anything achieved by having the extra _construct method not be achieved by just calling the parent constructor in the child class?

Nick
  • 6,967
  • 2
  • 34
  • 56

4 Answers4

70

Best answer I can find: http://www.magentocommerce.com/boards/viewthread/76027/#t282659

Basically, the root-level class (from which all other classes inherit) implements __construct, which PHP calls automatically whenever a class is constructed. Right now, this root-level class simply calls _construct, which contains the actual code.

Say you have this set-up:

class BaseClass {
   function __construct() {
       print "In BaseClass constructor\n";
       doSomethingReallyImportant();
   }
}

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

$obj = new BaseClass();
//"In BaseClass constructor"
//something really important happens

$obj = new SubClass();
//"In SubClass constructor"
//important thing DOESN'T happen

PHP doesn't automatically call the parent class constructors, so doSomethingReallyImportant never gets called. You could require that subclass constructors call parent::__construct(), but that's easy to forget. So Magento has subclasses override _construct:

class BaseClass {
   function __construct() {
       doSomethingReallyImportant();
      _construct();
   }
   function _construct() {
       print "In BaseClass constructor\n";
   }
}

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

$obj = new BaseClass();
//something really important happens
//"In BaseClass constructor"

$obj = new SubClass();
//something really important happens
//"In SubClass constructor"

PHP doesn't detect a constructor in SubClass, so it calls BaseClass's constructor. This allows BaseClass to doSomethingReallyImportant before calling SubClass's overridden _construct.

benesch
  • 5,239
  • 1
  • 22
  • 36
  • 1
    This is precisely the reason it exists. As a Magento developer, you should *never* override the `__construct` method, since everything in Magento extends `Varien_Object`. Not sure why this hasn't been accepted yet... – JMTyler Jan 03 '12 at 18:37
  • 1
    This isn't true for all classes. For example, observers will *not* call a _construct() method automatically. – Chris Rasys Nov 05 '14 at 19:17
  • Observers are the rare class in Magento that aren't supposed to (or at least aren't required) to extend a Varien/Mage class. If you aren't extending a base Varien class then the Varien-behavior of calling _construct() won't occur. – STW Nov 18 '14 at 19:37
4

To Marco: it is wrong to override __construct() method like this in Magento. The reason is - all classes inherit it from Varien_Object and it has this code:

#File: lib/Varien/Object.php 
public function __construct() 
{     
      //...snip...             
      $args = func_get_args();     
      if (empty($args[0])) 
      {         
          $args[0] = array();     
      }     
      //...snip... 
} 
//... 

With the __construct using your code, those arguments don’t get passed through. You really have to use Benesch's code:

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

Read more about this in Magento Block Lifecycle Methods by Alan Storm

PICher
  • 101
  • 3
3

Edit: sorry, missed the the difference between _construct and __construct in your question. I think the Magento programmers have tried to make it easier to override the constructor without the risk of their own constructor not being called anymore. The _construct method on Varien_Object is empty so it doesn't matter if it's not called from subclasses.


This is just how PHP implements constructors and destructors for classes. There's nothing Magento specific about it.

In other languages the constructor is usually implemented with a method having the same name as the class itself and the constructor usually has a tilde (~) in front of the method name baring the same name as the class. For some reason the PHP people have implemented it this way although PHP also seem to support constructors and destructors with the class name (link).

A class does not have to have a constructor and/or destructor, especially when you subclass another class. If you do override the constructor or destructor then you need to call the constructor or destructor of the overridden class manually by calling it on parent::, like:

class SubClass extends BaseClass {
   function __construct() {
       parent::__construct();
       // Your code
   }
   function __destruct() {
       // Your code
       parent::__destruct();
   }
}
STW
  • 44,917
  • 17
  • 105
  • 161
Marco Miltenburg
  • 6,123
  • 1
  • 29
  • 29
0

Single underscore construct (_construct) is used to avoid overriding the actual constructor with double underscore (__construct).

Example: vendor/magento/framework/Model/ResourceModel/AbstractResource.php

    /**
     * Constructor
     */
    public function __construct()
    {
        /**
         * Please override this one instead of overriding real __construct constructor
         */
        $this->_construct();
    }

    /**
     * Resource initialization
     *
     * @return void
     */
    abstract protected function _construct();
Mukesh Chapagain
  • 25,063
  • 15
  • 119
  • 120