Search code examples
phpstoragesplsplobjectstorage

What happens if the same object instance is attached multiple times to SplObjectStorage?


Or in other words, should I bother checking whether it already is in the set before attaching it?

$s = new SplObjectStorage();

foreach($arrayOfObjects as $primaryObject) {
    $subObject=$primaryObject->getSubObject();  //It is possible that a given instance of $subObject might be used in more than one $primaryObject
    if(!$s->contains($subObject)) {
        $s->attach($subObject);
    }
}

Solution

  • The "key" used internally by SplObjectStorage for each attached object is the hash of the given object (the same as returned by spl_object_hash).

    Each call to attach will effectively overwrite any existing object in the storage with the same hash (which should only happen if you're providing the same object), so there's no need to call contains before attaching an object.

    SplObjectStorage::attach($object) effectively means the same as

    $storage[spl_object_hash($object)] = $object;
    

    if you were using an array as your store instead.

    Full demo:

    class Foo {}
    $foo = new Foo;
    $s = new SplObjectStorage;
    
    echo $s->count(); // 0
    
    $s->attach($foo);
    echo $s->count(); // 1
    
    $s->attach($foo);
    echo $s->count(); // 1
    
    $s->detach($foo);
    echo $s->count(); // 0
    

    See https://3v4l.org/Rft7i