Detaching the current entry from the storage prevents SplObjectStorage::next() to operate.
Example as a PHPUnit-test:
<?php
public 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():
<?php
public 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.
PHP.mk документација
SplObjectStorage::detach
Почист и полокален преглед на PHP референцата, со задржана структура од PHP.net и подобра читливост за примери, секции и белешки.
Патека
splobjectstorage.detach.php
Локална патека за оваа страница.
Извор
php.net/manual/en
Оригиналниот HTML се реупотребува и локално се стилизира.
Режим
Прокси + превод во позадина
Кодовите, табелите и белешките остануваат читливи во истиот тек.
Референца
splobjectstorage.detach.php
SplObjectStorage::detach
Референца за `splobjectstorage.detach.php` со подобрена типографија и навигација.
SplObjectStorage::detach
(PHP 5 >= 5.1.0, PHP 7, PHP 8)
SplObjectStorage::detach — Отстранува object from the storage
Ги ескејпува специјалните знаци во стринг за употреба во SQL изјава
Оваа функција е DEPRECATED од PHP 8.5.0. Силно се обесхрабрува потпирањето на оваа функција.
= NULL
од PHP 8.4.0. Силно се обесхрабрува потпирањето на оваа функција.
public SplObjectStorage::detach(object
public SplObjectStorage::detach(object
$object): voidRemoves the object од складиштето.
Вратени вредности
Не се враќа вредност.
Примери
Пример #1 SplObjectStorage::detach() example
<?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)
Види Исто така
- SplObjectStorage::attach() - Додај ги сите објекти од друг склад
- SplObjectStorage::removeAll() - Отстранува објекти содржани во друго складиште од тековното складиште
Белешки од корисници 4 белешки
r dot wilczek at web-appz dot de ¶
пред 15 години
alan dot bem at gmail dot com ¶
12 години пред
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
nawa ¶
3 години пред
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 loop
foreach ($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 splObjectStorage
foreach ($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)
?>
Хејли Вотсон ¶
пред 8 години
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));
?>