# make new return a reference to existent object

- Thread: https://externals.io/message/16207
- Original archive: https://news-web.php.net/php.internals/16207
- Started by Duncan McIntyre on 2005-05-11T09:14:59+00:00
- Messages: 2
- Reply by email to internals@lists.php.net
- More for agents: search with https://externals.io/search.md?q={query} · JSON API at https://externals.io/api · documentation at https://externals.io/llms.txt

---

## #16207 — Duncan McIntyre — 2005-05-11T09:14:59+00:00

URL: https://externals.io/message/16207#16207

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

---

## #16212 — Leonardo Pedretti — 2005-05-11T15:48:45+00:00

URL: https://externals.io/message/16207#16212 · In reply to: #16207

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.


> 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
