Edit report at http://bugs.php.net/bug.php?id=52657&edit=1
ID: 52657
Comment by: rasmus at mindplay dot dk
Reported by: marco dot weber at uni-trier dot de
Summary: create a spl_object_id function
Status: Open
Type: Feature/Change Request
Package: SPL related
Operating System: ANY
PHP Version: Irrelevant
Block user comment: N
Private report: N
New Comment:
I don't think attaching a serial number to every object from the get-go is a
good
approach, since this will add overhead (memory and CPU) for every object
constructed. Objects are relatively lightweight in PHP, and sacrificing that
for a
feature that is probably less commonly used, to me, is unacceptable.
What I would propose, is to assign a serial number the first time you access an
object - something along the lines of this:
public function object_serial($object)
{
static $next_sn = 1;
if (!isset($object->__sn__))
$object->__sn__ = $next_sn++;
return $object->__sn__;
}
You don't need to keep a serial-number in-memory until it's actually needed,
and
at that point, we'll just check and see if it already has an assigned serial-
number.
This is much simpler and easier on system-resources - the serial number is much
lighter than the 32-character hash, and will work just as well. And since
you're
most likely going to use this value as index in an array, hash indexes will
take
up less memory, and lookups will probably be cheaper too.
Unfortunately the PHP version of this collides with the magic __set() method,
which is why the function shown above won't always work.
If there were a way to go around the __get() and __set() methods, and directly
access the properties of an object without colliding with these magic methods,
that would probably be an even better solution. I would consider such a feature
as
belonging to the reflection domain - something like
ReflectionObject::getValue($object, $name) and
ReflectionObject::setValue($object,
$name, $value) would do the trick.
(this would probably have other uses too, so perhaps that's an even better
solution to this problem, seeing as how implementing your own object_serial()
method is literally only a few lines of code...)
Previous Comments:
------------------------------------------------------------------------
[2011-06-13 10:44:11] marco dot weber at uni-trier dot de
i know, that there is nothing wrong with that method, as it does exactly, what
the documentation says. Nevertheless, it would be great to have another
function like spl_object_id(), that generates unique ids...
Quotation from [2010-08-20 15:34 UTC] marco dot weber at uni-trier dot de :
Since there is nothing wrong, with the spl_object_hash() method, i suggest to
introduce a new spl_object_id() function. This could simply return an
(internal) uint32, that is attached to every object on its creation. This
counter gets incremented on every object that gets created. :)
------------------------------------------------------------------------
[2011-06-13 04:18:41] rasmus at mindplay dot dk
I agree, this is a vital feature.
Also, the description of spl_object_hash() in the documentation is highly
misleading:
"This function returns a unique identifier for the object. This id can be used
as a hash key for storing objects or for identifying an object."
It does NOT always return a unique identifier, not even within a single running
script. And it CANNOT be used as a key for storing objects, neither can it be
used to identify an object. In fact, in the footnote, it basically says so:
"When an object is destroyed, its hash may be reused for other objects."
That fact precludes the uses mentioned in the first part of the documentation.
I don't know what the intended use of that function is. It seems like it was an
attempt to provide the functionality described in the first part of the
documentation, because those are definitely things that could be put to good
use
in object-relational mappers, test-frameworks, etc...
------------------------------------------------------------------------
[2010-08-21 07:59:04] giorgio dot liscio at email dot it
i've experienced problems with uniqueness ofspl_object_hash
i think should be rebuilt with a better one algorithm
there is no need (i think) of another function, just fix spl_object_hash
i think it is really important to fix
------------------------------------------------------------------------
[2010-08-20 17:38:19] marco dot weber at uni-trier dot de
i've forgotten to write down the test1 class:
class test1 {
public function __construct($s) { }
}
------------------------------------------------------------------------
[2010-08-20 17:34:25] marco dot weber at uni-trier dot de
Description:
------------
the problem with spl_object_hash is, that it is only unqiue for the existing
objects.
For a given Object:
class container {
protected $storage=array();
public function add(test1 $obj) {
if(!isset($this->storage[spl_object_hash($obj)])) {
$this->storage[spl_object_hash($obj)]=$obj;
}
}
}
This leads to a problem, that the add method receives the same hash in to
following cases:
CASE1:
$o=new container();
$o->add(new test1("lalala"));
$o->add(new test1("lololo")); // same hash, that's NOT ok!
CASE2:
$t=new test("lalala");
$o=new container();
$o->add($t);
$o->add($t); // same hash, that's ok!
Since there is nothing wrong, with the spl_object_hash() method, i suggest to
introduce a new spl_object_id() function. This could simply return an
(internal) uint32, that is attached to every object on its creation. This
counter gets incremented on every object that gets created. :)
Test script:
---------------
// just with spl_object_hash :/
class container {
protected $storage=array();
public function add(test1 $obj) {
if(!isset($this->storage[spl_object_hash($obj)])) {
$this->storage[spl_object_hash($obj)]=$obj;
}
}
}
$o=new container();
$o->add(new test1("lalala")); // will be added
$o->add(new test1("lololo")); // not added - NOT as expected
$t=new test("lalala");
$o=new container();
$o->add($t); // will be added
$o->add($t); // not added - as expected
Expected result:
----------------
// with the new spl_object_id function :)
class container {
protected $storage=array();
public function add(test1 $obj) {
if(!isset($this->storage[spl_object_id($obj)])) {
$this->storage[spl_object_id($obj)]=$obj;
}
}
}
$o=new container();
$o->add(new test1("lalala")); // will be added
$o->add(new test1("lololo")); // will be added
$t=new test("lalala");
$o=new container();
$o->add($t); // will be added
$o->add($t); // not added
------------------------------------------------------------------------
--
Edit this bug report at http://bugs.php.net/bug.php?id=52657&edit=1