Newsgroups: php.internals Path: news.php.net Xref: news.php.net php.internals:84657 Return-Path: Mailing-List: contact internals-help@lists.php.net; run by ezmlm Delivered-To: mailing list internals@lists.php.net Received: (qmail 29921 invoked from network); 12 Mar 2015 20:34:22 -0000 Received: from unknown (HELO lists.php.net) (127.0.0.1) by localhost with SMTP; 12 Mar 2015 20:34:22 -0000 Authentication-Results: pb1.pair.com header.from=rowan.collins@gmail.com; sender-id=pass Authentication-Results: pb1.pair.com smtp.mail=rowan.collins@gmail.com; spf=pass; sender-id=pass Received-SPF: pass (pb1.pair.com: domain gmail.com designates 209.85.212.173 as permitted sender) X-PHP-List-Original-Sender: rowan.collins@gmail.com X-Host-Fingerprint: 209.85.212.173 mail-wi0-f173.google.com Received: from [209.85.212.173] ([209.85.212.173:44058] helo=mail-wi0-f173.google.com) by pb1.pair.com (ecelerity 2.1.1.9-wez r(12769M)) with ESMTP id BA/67-24603-C48F1055 for ; Thu, 12 Mar 2015 15:34:22 -0500 Received: by wivr20 with SMTP id r20so860620wiv.3 for ; Thu, 12 Mar 2015 13:34:18 -0700 (PDT) DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=gmail.com; s=20120113; h=message-id:date:from:user-agent:mime-version:to:subject:references :in-reply-to:content-type:content-transfer-encoding; bh=kepvBAA84OPISxJinQqsT6gV3rIRZQdpbqw/rt9PNVQ=; b=wFVF9lrk+9+6JAqnoWtmPow3hLVb7ziGhC+XNS6loSnbgnPoxhADQ2gZUJv4kf415F 50GLHeK+UUBdpNayIlueb8SEFAA1j+0HYN6XDFfsoaeDDsa98ZxIndzQCP9OLiFmslS/ +aMljrLb3J4FA4OKaIYLqj05tsQ3dGdhUgBGLuhf60Cjl30fGJdrb142bE6jrQkKV5tu umu+uXheqCrrQUHw1H304kBv39xS5G4Vpp9MNHDDCK43Z1MPmB4vuCBU4/6u0ZOyM3FB L24sipAdXDnFYFLAtkENizlhH3qtfBb2HvlJxVfCZVzCXnWprAFC0kB6+3ek7nKJNEkO ADIw== X-Received: by 10.194.24.103 with SMTP id t7mr89330331wjf.15.1426192458043; Thu, 12 Mar 2015 13:34:18 -0700 (PDT) Received: from [192.168.0.159] ([62.189.198.114]) by mx.google.com with ESMTPSA id dc9sm30721228wib.9.2015.03.12.13.34.16 for (version=TLSv1.2 cipher=ECDHE-RSA-AES128-GCM-SHA256 bits=128/128); Thu, 12 Mar 2015 13:34:17 -0700 (PDT) Message-ID: <5501F823.3060805@gmail.com> Date: Thu, 12 Mar 2015 20:33:39 +0000 User-Agent: Mozilla/5.0 (Windows NT 6.1; WOW64; rv:31.0) Gecko/20100101 Thunderbird/31.5.0 MIME-Version: 1.0 To: internals@lists.php.net References: <6D.2C.32765.10EC0055@pb1.pair.com> <5500D967.5040800@gmail.com> <13.69.64353.73451055@pb1.pair.com> <5501876C.3020107@gmail.com> <3D.85.42021.3E7A1055@pb1.pair.com> <5501B77D.5010800@gmail.com> <85.D1.24603.247C1055@pb1.pair.com> <5501D328.9040800@gmail.com> <98.26.24603.C9DE1055@pb1.pair.com> In-Reply-To: <98.26.24603.C9DE1055@pb1.pair.com> Content-Type: text/plain; charset=utf-8; format=flowed Content-Transfer-Encoding: 7bit Subject: Re: [PHP-DEV] static constructor From: rowan.collins@gmail.com (Rowan Collins) Johannes Ott wrote on 12/03/2015 19:45: > All of the magic methods are doing like this. I thought you might say that, but the only thing remotely similar I can think of is a destructor, which gets called when an object goes out of scope; the others are all the implementation of, or instead of, some specific piece of code: __construct() runs every time for new Foo __get() and __set() runs every time for property access with -> on an undefined property __call() and __callStatic() runs every time for method access on an undefined property The difference with this is that you never know which part of your code will actually trigger it, because it only runs some of the time. > Okay thats a point I have to clearify I see, maybe my examples where to > much shorten by me. In my examples I'm showing only the initialize parts > of the classes, the initialized properties are used all over the class > in static as well in non-static context. OK, so these are classes which share certain resources between all instances, represented by these static properties. In that case, would it be reasonable to say that the initialization of these properties needs to happen the first time an instance is created? If so, the if(self::$initialized) check needs to run only as often as __construct(), not every time any method is called. If the static methods are public, and used for something other than managing instances (Factory / Singleton / etc), then are they really the responsibility of the same class? i.e. do you have a Utility class hiding in there pretending to be part of the instance/factory class? > For use case 1 the LogAdapter for example is a singleton instance per > class, that's why in my understanding of dependcy Injection it is not > working with it (correct me please if I'm wrong). And this singleton is > used to log in all methods of the class/object. In a system using Dependency Injection, all dependencies have to be passed in somewhere; a static dependency could be injected into a static property by a static method, but it still has to come from somewhere. Your implementation is pulling it from a global variable (or a public static, which is effectively the same thing) rather than waiting for it to be provided. Note also that you don't need to create 5 loggers just because you have 5 objects needing a logger - you pass in (or acquire from a global variable) references to the same instance each time - so the fact that it's an instance property rather than a static one is really no hardship. public function __construct() { $this->logger = LogAdapter::getLogger(self::class); } > Surely I would be able to get the specializied Singleton instance with > doing some code like the following two examples: > [examples trimmed] If not using any injection, I would implement it as follows: class A { private static $LOG; private static function getLogger() { if (self::$LOG = null) { self::$LOG = LogAdapter::getLogger(self::class); } return self::$LOG; } public static function a() { self::getLogger()->debug(); .... self::getLogger()->error(); } public function b() { ... self::getLogger()->error(); } ... } Not much more verbose than your version with __static, but a lot less magic, and therefore easier to debug. Slightly worse performance, with the extra method call, but I doubt if it would add up to enough to worry about. Thinking about it, you could even leave the way open for a different strategy by using $this->getLogger() instead of self::getLogger() - right now, that's 100% equivalent, but it makes it easier to change later to use injection, or be able to override the logger on particular instances, etc. This is often the problem with magic methods, be they at the language level or in a framework: they tend to lock you into working in a particular way, where more explicit code can be more readily refactored. Regards, -- Rowan Collins [IMSoP]