Re: make new return a reference to existent object

php.internals

Duncan McIntyre

21 years ago
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

Leonardo Pedretti

21 years ago
That is perfect Duncan, that was my first impression, but I think i read that there was something to adding new magic methods, however, i think that would be the perfect solution. On Wednesday 11 May 2005 06:14, Duncan McIntyre wrote:
> 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
-- Leonardo Pedretti Axon Sistemas Líder de Equipo Proyecto Basalto