Edit report at http://bugs.php.net/bug.php?id=52330&edit=1
ID: 52330 Updated by: ahar...@php.net Reported by: whistl0r+phpbug at googlemail dot com Summary: __construct() method should always return a new instance -Status: Open +Status: Wont fix Type: Bug Package: Class/Object related PHP Version: Irrelevant New Comment: That might seem odd, but it seems consistent enough to me. It breaks down one of two ways: 1. You call the constructor by instantiating an object with new. It behaves like a constructor -- return values are ignored and a new object instance is created. 2. You call the constructor by calling $object->__construct(). It behaves like a method call, including return values being returned. Basically, if you don't want __construct() to act like a method call, don't call it like a method call. Previous Comments: ------------------------------------------------------------------------ [2010-07-13 16:35:38] whistl0r+phpbug at googlemail dot com Description: ------------ Please see the test script. This should be normal PHP 5.3 class with a good OOP design. In PHP it is possible, that I can call the constructor multiple times, for example: $person = new \My\Person('Jens', 'Mander'); echo sprintf('Name: %s %s', $person->getName(), $person->getSurname()); // Will output "Name: Jens Mander" $person->__construct('John', 'Doe'); echo sprintf('Name: %s %s', $person->getName(), $person->getSurname()); // Will output "Name: John Doe" In my understanding, it is unexpected, that 1) you can access the constructor method in an instantiated object. The constructor should only instantiate the object - when you have the object, there is no need to call it again. If you need something to "reset" your object state, you should implement such a method. 2) If you can call the constructor again, that it will change the object and *not* return a new instance. For example: If you add a "return new \stdClass();" line to your constructor, it will still change the instance you called it from, but now it will also return a "stdClass" - that's inconsistent, isn't it? Test script: --------------- <?php namespace My; class Person { protected $_name = null; protected $_surname = null; /** * Constructor. * * @param string OPTIONAL $name * @param string OPTIONAL $surname * @return \My\Person */ public function __construct($name = null, $surname = null) { if ($name !== null) { $this->setName($name); } if ($surname !== null) { $this->setSurname($surname); } } /** * Returns the name. * * @return null|string Null, when no name was set */ public function getName() { return $this->_name; } /** * Returns the surname. * * @return null|string Null, when no name was set */ public function getSurname() { return $this->_surname; } /** * Set the name. * * @param string $name * @return \My\Person Provides fluent interface * @throws \Exception */ public function setName($name) { if (!is_string($name) || empty($name)) { throw new \Exception('Name cannot be empty and must be a string!'); } $this->_name = $name; return $this; } /** * Set the surname. * * @param string $name * @return \My\Person Provides fluent interface * @throws \Exception When $name isn't a string or empty */ public function setSurname($name) { if (!is_string($name) || empty($name)) { throw new \Exception('Name cannot be empty and must be a string!'); } $this->_surname = $name; return $this; } } Expected result: ---------------- - FATAL error e.g. "Object already constructed!" - The __construct() call should return a *new* object. Actual result: -------------- The __construct() method will work on the object, from where you called it. ------------------------------------------------------------------------ -- Edit this bug report at http://bugs.php.net/bug.php?id=52330&edit=1