On 1/12/2017 9:35 PM, Marco Pivetta wrote: > Heya, > > While I agree that it is weird to be able to call constructors more than > once, this is generally used for: > > * lazy loading > * resource reset > > Specifically, what is going on is something like following:<?php > > final class DbConnection > { > private $dsn; > private $initializer; > public function __construct(string $dsn) > { > $this->dsn = $dsn; > // socket stuff happens here, much like with PDO > } > > public function query(string $queryString) : array > { > ($this->initializer)(); > // irrelevant from here on > return ['query' => $queryString, 'dsn' => $this->dsn]; > } > > public static function lazyInstance(string $dsn) : self > { > $instance = (new > ReflectionClass(self::class))->newInstanceWithoutConstructor(); > $instance->initializer = function () use ($dsn, $instance) { > $instance->__construct($dsn); > $instance->initializer = function () { > }; > }; > return $instance; > } > } > > $instance = DbConnection::lazyInstance('mysql://something'); > > var_dump($instance); > > var_dump($instance->query('SELECT * FROM foo')); > var_dump($instance->query('SELECT * FROM bar')); > > Here's an example of it at work: https://3v4l.org/Y0eoL > > The pattern is simple: > > * intercept constructor call > * capture constructor parameters > * instantiate without constructor > * defer constructor call for later > > The same can be used in a myriad of different ways, but this is a legit > use-cases that generally don't involve coding everything into the same > class (and I generally advise against doing that anyway). > > Therefore I don't see a reason to drop manual constructor calls, unless > there is a strong necessity to get rid of 'em. > > > > Marco Pivetta >
Very creative but why not the following? ``` <?php final class DbConnection { private $dsn; private $initialized = false; public function __construct($dsn) { $this->dsn = $dsn; } private function init() { $this->initialized = true; echo $this->dsn , "\n"; } public function query($queryString) { // this is actually cheaper than calling the closure $this->initialized || $this->init(); return ['query' => $queryString, 'dsn' => $this->dsn]; } } $db_conn = new DbConnection('mysql://something'); var_dump( $db_conn, $db_conn->query('SELECT * FROM foo'), $db_conn->query('SELECT * FROM bar') ); ``` https://3v4l.org/PaqqZ Works equally well in PHP and HHVM and achieves your goal without using undocumented side effects and reflection. Adding the ability of a non-lazy and lazy construction is easily added too if desired. -- Richard "Fleshgrinder" Fussenegger -- PHP Internals - PHP Runtime Development Mailing List To unsubscribe, visit: http://www.php.net/unsub.php