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