I've been wondering, is such a thing even possible? Is there a good way
to implement an object destruct order? Here are my thoughts:
In the class definition, specify what "level" of destruction the objects
should be on. How, I have no idea, I haven't thought of a good syntax.
It should be an integer for what level though.
Then when the script ends, the engine starts with the highest most level
of destruction. It continues down until everything has been destructed.
With the last most level being objects with unspecified levels.
Note: Each level can have more than one class.
Example destruction order:
3 = database records (ActiveRecord or such)
2 = database connection object
1 = framework objects
0 = objects with unspecified level
I've been wondering, is such a thing even possible? Is there a good way to
implement an object destruct order? Here are my thoughts:In the class definition, specify what "level" of destruction the objects
should be on. How, I have no idea, I haven't thought of a good syntax. It
should be an integer for what level though.Then when the script ends, the engine starts with the highest most level of
destruction. It continues down until everything has been destructed. With
the last most level being objects with unspecified levels.Note: Each level can have more than one class.
Example destruction order:
3 = database records (ActiveRecord or such)
2 = database connection object
1 = framework objects
0 = objects with unspecified level
Why would you need such thing?
PHP uses reference-counting and destroys objects as soon, as there are
no more references to them. Since PHP 5.3, it also detects
cyclic-references and periodically destroys object-groups which have
references to each other, but do not have references from external
context.
--
Alexey Zakhlestin
http://blog.milkfarmsoft.com/
Alexey Zakhlestin wrote:
I've been wondering, is such a thing even possible? Is there a good way to
implement an object destruct order? Here are my thoughts:In the class definition, specify what "level" of destruction the objects
should be on. How, I have no idea, I haven't thought of a good syntax. It
should be an integer for what level though.Then when the script ends, the engine starts with the highest most level of
destruction. It continues down until everything has been destructed. With
the last most level being objects with unspecified levels.Note: Each level can have more than one class.
Example destruction order:
3 = database records (ActiveRecord or such)
2 = database connection object
1 = framework objects
0 = objects with unspecified levelWhy would you need such thing?
PHP uses reference-counting and destroys objects as soon, as there are
no more references to them. Since PHP 5.3, it also detects
cyclic-references and periodically destroys object-groups which have
references to each other, but do not have references from external
context.
Additionally, AFAIK in an ideal situation a destructor should only
destroy objects which exist during the lifetime of an instance of the
class containing the destructor.
If objects have a greater lifespan (i.e. shared) then they should be
destroyed by other means, like at the end of their lifespan or at the
end of your script.
I've been wondering, is such a thing even possible? Is there a good way
to
implement an object destruct order? Here are my thoughts:In the class definition, specify what "level" of destruction the objects
should be on. How, I have no idea, I haven't thought of a good syntax.
It
should be an integer for what level though.Then when the script ends, the engine starts with the highest most level
of
destruction. It continues down until everything has been destructed.
With
the last most level being objects with unspecified levels.Note: Each level can have more than one class.
Example destruction order:
3 = database records (ActiveRecord or such)
2 = database connection object
1 = framework objects
0 = objects with unspecified level
Hi,
This would likely (and possibly rightfully) be frowned upon, but according
to the current codebase, if the destructor creates a new reference outside
to the destroyed object while it runs, the object won't be garbage collected
(a safe call is used that checks for any remaining references after the
destructor is called).
This allows you to implement destruction priorities yourself easily by using
a central "DestructManager":
function __destruct()
{
global $destructManager;
$this->addObject($this, $priority);
}
function __real_destruct()
{
....
}
Those will be collected in the destruction manager and when at shutdown, on
the manager's own destructor you just need to sort the collection by
priority and call the "real" destructor.
Now, this will work fine, but has this downside that all objects will be
held in the memory until script shutdown, so it's naturally not good for
long running processes.
Regards,
Stan Vassilev
Hi,
Naturally this line:
"$this->addObject($this, $priority);"
was meant to be:
$destructManager->addObject($this, $priority);" ...
Regards,
Stan Vassilev
On Wednesday 22 October 2008 2:31:38 am Mike van Riel wrote:
Example destruction order:
3 = database records (ActiveRecord or such)
2 = database connection object
1 = framework objects
0 = objects with unspecified levelWhy would you need such thing?
PHP uses reference-counting and destroys objects as soon, as there are
no more references to them. Since PHP 5.3, it also detects
cyclic-references and periodically destroys object-groups which have
references to each other, but do not have references from external
context.Additionally, AFAIK in an ideal situation a destructor should only
destroy objects which exist during the lifetime of an instance of the
class containing the destructor.
If objects have a greater lifespan (i.e. shared) then they should be
destroyed by other means, like at the end of their lifespan or at the
end of your script.
I believe the "end of your script" part is the problem. Imagine you have some
object (say, ActiveRecord style) that writes itself to the database when it's
destroyed if the data has been modified. Now cache that object in a static
variable somewhere for performance. You're also using PDO, so your database
connection is a global or singleton instance of the PDO class.
Then your script reaches the end. Does your object get destroyed and
therefore saved to the database before or after the PDO object goes away? I
don't actually know.
I'm not saying that manual destructor order is the correct way to deal with
that issue necessarily, but I think that's the sort of use case it's intended
to address.
--
Larry Garfield
larry@garfieldtech.com
I believe the "end of your script" part is the problem. Imagine you
have some
object (say, ActiveRecord style) that writes itself to the database
when it's
destroyed if the data has been modified. Now cache that object in a
static
variable somewhere for performance. You're also using PDO, so your
database
connection is a global or singleton instance of the PDO class.Then your script reaches the end. Does your object get destroyed and
therefore saved to the database before or after the PDO object goes
away? I
don't actually know.I'm not saying that manual destructor order is the correct way to
deal with
that issue necessarily, but I think that's the sort of use case it's
intended
to address.
If you want to treat a PHP script as a traditional application, you
should be prepared to unset() and keep references of everything
yourself. Relying on the garbage collector for your business logic to
work is just bad design.
I'd personally always explicitly do a ->saveObject in similar
situations as its predictable and quite frankly never found a use for
a destructor other than debugging..
Sounds like a subject that doesn't belong on PHP-DEV in any event.
Evert
"The destructor method will be called as soon as all references to a
particular object are removed or when the object is explicitly destroyed
or in any order in shutdown sequence."
As far as I understand it if your active record references the PDO
instance (say $this->conn) your object gets destroyed before the
connection object.
Perhaps it's a better approach then introducing destruction order for
global or singleton problems.
wbr,
Diogo
Larry Garfield wrote:
On Wednesday 22 October 2008 2:31:38 am Mike van Riel wrote:
I believe the "end of your script" part is the problem. Imagine you have some
object (say, ActiveRecord style) that writes itself to the database when it's
destroyed if the data has been modified. Now cache that object in a static
variable somewhere for performance. You're also using PDO, so your database
connection is a global or singleton instance of the PDO class.Then your script reaches the end. Does your object get destroyed and
therefore saved to the database before or after the PDO object goes away? I
don't actually know.I'm not saying that manual destructor order is the correct way to deal with
that issue necessarily, but I think that's the sort of use case it's intended
to address.
Diogo Galvão wrote:
"The destructor method will be called as soon as all references to a
particular object are removed or when the object is explicitly destroyed
or in any order in shutdown sequence."As far as I understand it if your active record references the PDO
instance (say $this->conn) your object gets destroyed before the
connection object.Perhaps it's a better approach then introducing destruction order for
global or singleton problems.wbr,
DiogoLarry Garfield wrote:
On Wednesday 22 October 2008 2:31:38 am Mike van Riel wrote:
I believe the "end of your script" part is the problem. Imagine you
have some object (say, ActiveRecord style) that writes itself to the
database when it's destroyed if the data has been modified. Now cache
that object in a static variable somewhere for performance. You're
also using PDO, so your database connection is a global or singleton
instance of the PDO class.
Then your script reaches the end. Does your object get destroyed and
therefore saved to the database before or after the PDO object goes
away? I don't actually know.I'm not saying that manual destructor order is the correct way to deal
with that issue necessarily, but I think that's the sort of use case
it's intended to address.
just to add it in; in ejb3 in java you have PostConstruct and PreDestroy
which are pretty useful; maybe something along the same lines could be
implemented in PHP?
regards!
--
nathan ( nathan@kraya.co.uk )
{
Senior Web Developer
php + java + flex + xmpp + xml + ecmascript
web development edinburgh | http://kraya.co.uk/
}
Nathan Rixham wrote:
Diogo Galvão wrote:
"The destructor method will be called as soon as all references to a
particular object are removed or when the object is explicitly destroyed
or in any order in shutdown sequence."As far as I understand it if your active record references the PDO
instance (say $this->conn) your object gets destroyed before the
connection object.Perhaps it's a better approach then introducing destruction order for
global or singleton problems.wbr,
DiogoLarry Garfield wrote:
On Wednesday 22 October 2008 2:31:38 am Mike van Riel wrote:
I believe the "end of your script" part is the problem. Imagine you
have some object (say, ActiveRecord style) that writes itself to the
database when it's destroyed if the data has been modified. Now
cache that object in a static variable somewhere for performance.
You're also using PDO, so your database connection is a global or
singleton instance of the PDO class. Then your script reaches the
end. Does your object get destroyed and therefore saved to the
database before or after the PDO object goes away? I don't actually
know.I'm not saying that manual destructor order is the correct way to
deal with that issue necessarily, but I think that's the sort of use
case it's intended to address.just to add it in; in ejb3 in java you have PostConstruct and PreDestroy
which are pretty useful; maybe something along the same lines could be
implemented in PHP?
Or perhaps you should just stick with Java?
--Jani
Jani Taskinen wrote:
Nathan Rixham wrote:
just to add it in; in ejb3 in java you have PostConstruct and
PreDestroy which are pretty useful; maybe something along the same
lines could be implemented in PHP?Or perhaps you should just stick with Java?
just a suggestion for some useful functionality - where's the harm?
anyhow, apologies if I offended - have a great day :-)
I think this should be implemented by user. If you are full OOP in your
application, then just register all your objects in some global object (In
my case I have a global singelton) and trigger hiv removal at the end of
your application. If you have destructors written in every object - they
will be destroied by chain correctly. Yes, this is design featchure, but a
good one, because if you will move beyound PHP you will have to learn how to
do it anyway sooner or laiter :)
User knows the best how his objects should be destroied. PHP is slow
enougth, any special functionality will make it more slow. Let's let
developers do the optimization work for a while, may be they will find a way
how to significantly boost PHP speed :)
Hello Ryan,
during 5.0 alpha phase I had that actually implemented. But it turned
out to be too much of a slowdown and also could not solve all dependency
graphs. For example you can obviously not solve dependency cycles. So at
the end of the experiement we decided against it.
Maybe we could implement a function that triggers ordered shutdown, so that
the user has the choice of doing it as good as possible.
marcus
Wednesday, October 22, 2008, 3:03:18 AM, you wrote:
I've been wondering, is such a thing even possible? Is there a good way
to implement an object destruct order? Here are my thoughts:
In the class definition, specify what "level" of destruction the objects
should be on. How, I have no idea, I haven't thought of a good syntax.
It should be an integer for what level though.
Then when the script ends, the engine starts with the highest most level
of destruction. It continues down until everything has been destructed.
With the last most level being objects with unspecified levels.
Note: Each level can have more than one class.
Example destruction order:
3 = database records (ActiveRecord or such)
2 = database connection object
1 = framework objects
0 = objects with unspecified level
Best regards,
Marcus
2008/10/22 Ryan Panning rpanning@gmail.com:
I've been wondering, is such a thing even possible? Is there a good way to
implement an object destruct order? Here are my thoughts:In the class definition, specify what "level" of destruction the objects
should be on. How, I have no idea, I haven't thought of a good syntax. It
should be an integer for what level though.Then when the script ends, the engine starts with the highest most level of
destruction. It continues down until everything has been destructed. With
the last most level being objects with unspecified levels.Note: Each level can have more than one class.
Example destruction order:
3 = database records (ActiveRecord or such)
2 = database connection object
1 = framework objects
0 = objects with unspecified level--
I solved my issues by adding the concept of "owner" to my base object class.
So any instance not "owned", I'm saying I don't care about destruction order.
For all "owned" instances, it is my responsibility to call the
destructor of the root(s) of the owned instances.
Having an array of references of the parent/child relationship (every
parent knows its children and every child knows its parent) you can
destroy all the children in FILO order before destroying self.
It seems that you can't REALLY destroy an instance inside the
destructor so I needed to "tag" instances as dead.
That combined with a few methods to deal with adding a "child" and
notifying of the change of ownership ($_obj_Owner is private) this
works for me.
I think having the base object supporting this concept would go a long
way to allowing the developer decide when they had finished with
things.
Of course, this is probably more suited to long running apps rather
than web scripts, true.
I used to program using Delphi, and that is where I took this idea.
I'm sure other languages have this.
All my script start with a base class_App which is nothing more than a
container for other instances and is a catch all for any unowned
instance. All instances are destroyed specifically in reverse order -
FILO - First In Last Out. Fortunately, I've not needed out of order
destruction yet.
Richard.
--
Richard Quadling
Zend Certified Engineer : http://zend.com/zce.php?c=ZEND002498&r=213474731
"Standing on the shoulders of some very clever giants!"
Ryan Panning wrote:
I've been wondering, is such a thing even possible? Is there a good way
to implement an object destruct order? Here are my thoughts:In the class definition, specify what "level" of destruction the objects
should be on. How, I have no idea, I haven't thought of a good syntax.
It should be an integer for what level though.Then when the script ends, the engine starts with the highest most level
of destruction. It continues down until everything has been destructed.
With the last most level being objects with unspecified levels.Note: Each level can have more than one class.
Example destruction order:
3 = database records (ActiveRecord or such)
2 = database connection object
1 = framework objects
0 = objects with unspecified level
Hi, I've been out sick the past couple days so I haven't been able to
keep on eye on this. Thanks for all the feedback, all good points.
As for the comments about bad practice: I understand that it's not the
best thing to rely on. But, when you have objects relying on other
objects to do things (may not have a reference to them), it's hard to
use the __destruct() method. In which case makes __destruct() not all
that useful.
As for comments about different approaches: Making my own shutdown
process is what I and I'm assuming everyone else has been doing.
However, I'm just thinking that if there was a built-in way of doing
this that it would be easier to make cross-application plugin types of
things.
Marcus: Interesting, I didn't know you had tried this already. Good to
know that you've tested it.
Pre-destruction method: I like the idea about a pre-destruction method.
It would give the user a chance to do something before other objects are
destroyed. Is this something that would slow down PHP too much?