Re: static constructor

From: Date: Sun, 15 Mar 2015 22:17:05 +0000
Subject: Re: static constructor
References: 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20  Groups: php.internals 
Request: Send a blank email to internals+get-84943@lists.php.net to get a copy of this message
On 15/03/2015 20:52, Johannes Ott wrote:
Am 15.03.2015 um 19:47 schrieb Rowan Collins:
On 15/03/2015 10:41, Johannes Ott wrote:
Okay get your point, but as already discussed several times, the rfc should not be declined for the reason a ppl, who doesn't understand when to use static context or when not to use at all, can do crucial things. Because he although can do without the static constructor. For a horiffic example: class Example {
       private static $handler;
       public function open() {
           self::$handler = fopen('example.txt');
       }
       ...
} Example::open(); Indeed I have the opinion some beginner who is doing such horiffic code maybe think more about what he is doing and especially about the side effects inside a so called "magic" method, then outside.
I'm not clear what's so different between this and your logger example. Here you have a file handle, which in PHP happens to be a special type rather than an object, and are storing it in a static property; closing the file handle has to be managed somehow, and this code is letting PHP do this implicitly with what amounts to a destructor on the file handle resource.
The difference is as I told the Resource Handler is wrapped inside a Singleton Instance with a destructor!
Whether the instance is a singleton, or has a non-default destructor, makes no difference - the cleanup happens during PHP's shutdown procedure. As it happens, resources have the equivalent of destructors internally, so even the object instance vs resource doesn't actually matter here.
Or, you can *invalidate* the objects, rather than destructing them, as implied by your "DBAdapter::closeAllConnections()" example - there will still be references to those connections live in your code if, for instance, you have Example::$logger, and $logger->dbConnection. You can't have an Example::cleanupResources() method, because it would fire the static constructor on pages which hadn't used the class yet, destroying the lazy-loading.
You always talking about the singleton-pattern, as I although told different times now, I have no resources directly stored in static context but in singleton instances inside. for example the DBAdapter::closeAllConnections(): public static closeAllConnections() {
     while(count(self::$connections) > 0) {
         self::$connections[0]->close();
         unset(self::$connections[0]);
     }
} the same for LogAdapter.
This doesn't destroy those objects - PHP is a purely garbage collected language (in the sense of no manually managed memory / resources), so you can't destroy an object something still points to. If you gave out a reference to a DB connection and stored it in a static variable somewhere, that reference still ponts to the object, and you will have to detect that it is a closed connection and handle it appropriately. This isn't to do with public constructors vs singletons, or even objects vs resources, it's about the handle being shared amongst multiple users, no one of which can unilaterally "unshare" it. My point about lazy-loading is that if you have a class like this... class LazyThing { private static $foo; private function __static() { self::$foo = Something::GetSomeKindOfWrappedResource(); } public function cleanup() { self::$foo->destroy(); } } ...and then don't need it on a particular page, when you call LazyThing::cleanup(), it will actually trigger the static constructor, potentially triggering a whole chain of resources to be opened just in order to close them again. If that's the case, then you might as well have a matching pair of Foo::initialise() and Foo::cleanup() calls which are both called explicitly. So explicit cleanup routines can't usefully be used in the same class as implicit initialisation, which kind of makes sense, but rules them out as an alternative to static destructors. Regards, -- Rowan Collins [IMSoP]

« previous php.internals (#84943) next »