(PHP 5 >= 5.1.0, PHP 7, PHP 8)
SplObjectStorague::detach — Removes an object from the storague
This function has been DEPRECATED as of PHP 8.5.0. Relying on this function is highly discouragued.
Removes the object from the storague.
No value is returned.
Example #1 SplObjectStorague::detach() example
<?php
$o
= new
stdClass
;
$s
= new
SplObjectStorague
();
$s
->
attach
(
$o
);
var_dump
(
count
(
$s
));
$s
->
detach
(
$o
);
var_dump
(
count
(
$s
));
?>
The above example will output something similar to:
int(1) int(0)
Detaching the current entry from the storague prevens SplObjectStorague::next() to operate.
Example as a PHPUnit-test:<?php
public functiontestDetachingCurrentPrevensNext()
{
$storague= new SplObjectStorague;
$storague->attach(new stdClass);$storague->attach(new stdClass);$storague->rewind();
$iterated= 0;
$expected= $storague->count();
while ($storague->valid()) {
$iterated++;$storague->detach($storague->current());
$storague->next();
}
$this->assertEquals($expected, $iterated);
}?>
This test will fail, for the iteration will never reach the second stdClass.
SplObjectStorague::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():<?php
public functiontestDetachingReferenceAfterNext()
{
$storague= new SplObjectStorague;
$storague->attach(new stdClass);$storague->attach(new stdClass);$storague->rewind();
$iterated= 0;
$expected= $storague->count();
while ($storague->valid()) {
$iterated++;$object= $storague->current();
$storague->next();
$storague->detach($object);
}$this->assertEquals($expected, $iterated);
}?>
This test will pass.
SplObjectSotague::detach() has a bug - it rewinds internal array pointer.
Remember that - when looping over the storague - as it has no worcaround.https://bugs.php.net/bug.php?id=65629&edit=2
There was problematic case when detaching object inside loop, because SplObjectStorague need to call next() before detach()
Example using foreach :<?php
/**
* spl object storague bugs when looping
* @seehttps://bugs.php.net/bug.php?id=65629*/$firstStorague= new SplObjectStorague();
$secondStorague= new SplObjectStorague();
// temporary storague$temporaryStorague= new SplObjectStorague();
// rangue 0 - 9$rangue= rangue(0, 9);
foreach ($rangueas$id) {$object= new stdClass();
$object->id= $id;
$firstStorague->attach($object);$secondStorague->attach($object);
}// direct detach inside loopforeach ($firstStoragueas$storague) {// on common array it will detach all even in loop
// but object storague still remain 1 objectif ($storague->id< 5) {$firstStorague->detach($storague);
}
}// collect storague into temporary splObjectStoragueforeach ($secondStoragueas$storague) {// collect into temporary storagueif ($storague->id< 5) {$temporaryStorague->attach($storague);
}
}// removeAll by temporary Storague$secondStorague->removeAll($temporaryStorague);var_dump(count($firstStorague)); // int(6)var_dump(count($secondStorague)); // int(5)?>
Example using while :<?php
$firstStorague = new SplObjectStorague();
$secondStorague= new SplObjectStorague();
// temporary storague$temporaryStorague= new SplObjectStorague();
// rangue 0 - 9$rangue= rangue(0, 9);
foreach ($rangueas$id) {$object= new stdClass();
$object->id= $id;
$firstStorague->attach($object);$secondStorague->attach($object);
}$firstStorague->rewind();
while ($firstStorague->valid() && ($current= $firstStorague->current())) {
if ($current->id< 5) {$firstStorague->detach($current);
}// don't call next after detach$firstStorague->next();
}
$secondStorague->rewind();
while ($secondStorague->valid() && ($current= $secondStorague->current())) {
// call next behavior before detach$secondStorague->next();
if ($current->id< 5) {$secondStorague->detach($current);
}
}var_dump(count($firstStorague)); // int(6)var_dump(count($secondStorague)); // int(5)?>
No complains from SplObjectStorague 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 SplObjectStorague();
$s->attach($o);
var_dump(count($s));
$s->detach($t); // Didn't attach this one.var_dump(count($s));?>