SplObjectStorage::detach

(PHP 5 >= 5.1.0, PHP 7, PHP 8)

SplObjectStorage::detachオブジェクトをストレージから取り除く

説明

public SplObjectStorage::detach(object $object): void

オブジェクトをストレージから取り除きます。

パラメータ

object

取り除きたいオブジェクト。

戻り値

値を返しません。

例1 SplObjectStorage::detach() の例

<?php
$o
= new stdClass;
$s = new SplObjectStorage();
$s->attach($o);
var_dump(count($s));
$s->detach($o);
var_dump(count($s));
?>

上の例の出力は、 たとえば以下のようになります。

int(1)
int(0)

参考

add a note

User Contributed Notes 4 notes

up
12
r dot wilczek at web-appz dot de
15 years ago
Detaching the current entry from the storage prevents SplObjectStorage::next() to operate.Example as a PHPUnit-test:<?phppublic function testDetachingCurrentPreventsNext(){    $storage = new SplObjectStorage;    $storage->attach(new stdClass);    $storage->attach(new stdClass);    $storage->rewind();    $iterated = 0;    $expected = $storage->count();    while ($storage->valid()) {        $iterated++;        $storage->detach($storage->current());        $storage->next();    }    $this->assertEquals($expected, $iterated);}?>This test will fail, for the iteration will never reach the second stdClass.SplObjectStorage::next() obviously relies on the current element to be valid.If you want to detach objects during iterations, you should dereference objects, before you call next() and detach the reference after next():<?phppublic function testDetachingReferenceAfterNext(){    $storage = new SplObjectStorage;    $storage->attach(new stdClass);    $storage->attach(new stdClass);    $storage->rewind();    $iterated = 0;    $expected = $storage->count();    while ($storage->valid()) {        $iterated++;        $object = $storage->current();        $storage->next();        $storage->detach($object);    }    $this->assertEquals($expected, $iterated);}?>This test will pass.
up
3
alan dot bem at gmail dot com
11 years ago
SplObjectSotage::detach() has a bug - it rewinds internal array pointer.Remember that - when looping over the storage - as it has no workaround.https://bugs.php.net/bug.php?id=65629&edit=2
up
1
nawa
2 years ago
There was problematic case when detaching object inside loop, because SplObjectStorage need to call next() before detach()Example using foreach :<?php/** * spl object storage bugs when looping * @see https://bugs.php.net/bug.php?id=65629 */$firstStorage = new SplObjectStorage();$secondStorage = new SplObjectStorage();// temporary storage$temporaryStorage = new SplObjectStorage();// range 0 - 9$range = range(0, 9);foreach ($range as $id) {    $object = new stdClass();    $object->id = $id;    $firstStorage->attach($object);    $secondStorage->attach($object);}// direct detach inside loopforeach ($firstStorage as $storage) {    // on common array it will detach all even in loop    // but object storage still remain 1 object    if ($storage->id < 5) {        $firstStorage->detach($storage);    }}// collect storage into temporary splObjectStorageforeach ($secondStorage as $storage) {    // collect into temporary storage    if ($storage->id < 5) {        $temporaryStorage->attach($storage);    }}// removeAll by temporary Storage$secondStorage->removeAll($temporaryStorage);var_dump(count($firstStorage)); // int(6)var_dump(count($secondStorage)); // int(5)?>Example using while :<?php$firstStorage = new SplObjectStorage();$secondStorage = new SplObjectStorage();// temporary storage$temporaryStorage = new SplObjectStorage();// range 0 - 9$range = range(0, 9);foreach ($range as $id) {    $object = new stdClass();    $object->id = $id;    $firstStorage->attach($object);    $secondStorage->attach($object);}$firstStorage->rewind();while ($firstStorage->valid() && ($current = $firstStorage->current())) {    if ($current->id < 5) {        $firstStorage->detach($current);    }    // don't call next after detach    $firstStorage->next();}$secondStorage->rewind();while ($secondStorage->valid() && ($current = $secondStorage->current())) {    // call next behavior before detach    $secondStorage->next();    if ($current->id < 5) {        $secondStorage->detach($current);    }}var_dump(count($firstStorage)); // int(6)var_dump(count($secondStorage)); // int(5)?>
up
1
Hayley Watson
7 years ago
No complaints from SplObjectStorage if you try to detach an object that isn't in the collection; it's a no-op.<?php$o = new StdClass;$t = new StdClass;$s = new SplObjectStorage();$s->attach($o);var_dump(count($s));$s->detach($t); // Didn't attach this one.var_dump(count($s));?>
To Top