Wez,

I have similar problems. I think your suggested solution is the wrong approach 
because your problem is not creating objects, it is destroying them.

My solution would be to define a new magic static method __free() which is 
given an instance of the class every time a reference to that instance is 
deleted. This would be a hook into the code which calls __destruct() once an 
object's ref count reaches zero, except that it would call __free() every 
time an object's ref count was decremented.

class SomeClass {
        public static __free($instance) {
                /**
                * Do some static instance caching magic here
                **/
        }
}

This would be a neat addition to the language, but unless it is implemented 
you will have to use a bit of discipline in writing your code instead.

The example below is probably the best you can do:

/**
* This class provides the mechanism to load objects from the database
* and caches loaded instances
**/
class ObjectStore {

        static $instances=array();

        public static function loadObject($class, $id) {
                if(isset(ObjectStore::instances[$class][$id])) {
                        ObjectStore::instances[$class][$id][1]++;
                        return ObjectStore::instances[$class][$id][0];
                }

                $handle = SomeDatabaseClass::getHandle();
                $result = $handle->query("SELECT * FROM $class WHERE id=$id");
                if(!$result->num_rows()) {
                        throw new Exception("Object $class $id does not exist 
in the database");
                }
                $r = $result->fetch_object();
                $obj = new $class();
                $obj->deserialize($r);
                ObjectStore::instances[$class][$id]=array($obj, 1);
                return $obj;
        }

        public static function free($obj) {
                ObjectStore::instances[$obj->class][$obj->id][1]--;
                if(!ObjectStore::instances[$obj->class][$obj->id][1]) {
                        unset(ObjectStore::instances[$obj->class][$obj->id]);
                }
        }
}

/**
* All classes stored in the database must extend this class
**/
abstract class PersistentObject {
        public function free() {
                static $freed;
                if(!$freed) {
                        ObjectStore::free($this);
                        $freed=true;
                }
                return $this;
        }

        /**
        * Retrieve the object's properties from a database row
        **/
        abstract public function deserialize($db_object);
}

Then load objects by calling

$obj = ObjectStore::loadObject("SomeClass",27); 
And when you're done with them call unset($obj->free());

Any classes which consume PersistentObjects must have a method __destruct()
which calls free() on any PersistentObjects they have references to in order 
for this to work.

Duncan

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

Reply via email to