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]


--
PHP Internals - PHP Runtime Development Mailing List
To unsubscribe, visit: http://www.php.net/unsub.php

Reply via email to