Newsgroups: php.internals Path: news.php.net Xref: news.php.net php.internals:16207 Return-Path: Mailing-List: contact internals-help@lists.php.net; run by ezmlm Delivered-To: mailing list internals@lists.php.net Received: (qmail 17996 invoked by uid 1010); 11 May 2005 08:36:56 -0000 Delivered-To: ezmlm-scan-internals@lists.php.net Delivered-To: ezmlm-internals@lists.php.net Received: (qmail 95702 invoked from network); 11 May 2005 08:16:43 -0000 Received: from unknown (HELO jirsahedrick.com) (127.0.0.1) by localhost with SMTP; 11 May 2005 08:16:43 -0000 X-Host-Fingerprint: 212.69.217.33 smtp-relay04.x-mailer.co.uk Linux 2.4/2.6 Received: from ([212.69.217.33:45891] helo=smtp-relay04.x-mailer.co.uk) by pb1.pair.com (ecelerity 1.2 r(5656M)) with SMTP id DB/E7-35155-86FB1824 for ; Wed, 11 May 2005 04:16:41 -0400 Received: from [212.69.210.169] (helo=emarket.dsvr.co.uk) by smtp-relay04.x-mailer.co.uk with esmtp (Exim 4.30) id 1DVmOT-00037f-8Q; Wed, 11 May 2005 09:16:37 +0100 Received: from variable ([82.153.149.65]) (authenticated (0 bits)) by emarket.dsvr.co.uk (8.11.7/8.11.7) with ESMTP id j4B8Gah30094; Wed, 11 May 2005 09:16:37 +0100 Organization: Calligram Ltd To: Wez Furlong Date: Wed, 11 May 2005 10:14:59 +0100 User-Agent: KMail/1.7.1 Cc: internals@lists.php.net MIME-Version: 1.0 Content-Type: text/plain; charset="iso-8859-1" Content-Transfer-Encoding: 7bit Content-Disposition: inline Message-ID: <200505111014.59892.duncan@calligram.co.uk> Subject: Re: [PHP-DEV] make new return a reference to existent object From: duncan@calligram.co.uk (Duncan McIntyre) 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