PHP Conference Nagoya 2025

SplDoublyLinkedList::shift

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

SplDoublyLinkedList::shiftShifts a node from the beginning of the doubly linked list

说明

public SplDoublyLinkedList::shift(): mixed

参数

此函数没有参数。

返回值

The value of the shifted node.

错误/异常

Throws RuntimeException when the data-structure is empty.

添加备注

用户贡献的备注 1 note

up
1
fabs2s at marsatak dot org
7 years ago
One may expect SplDoublyLinkedList::shift to properly maintain internal pointers, but this is not the case, this will yield no results, even if you rewind first

<?php
while ($splDoublyLinkedList->valid()) {
yield
$splDoublyLinkedList->shift();
}
?>

It could be by design, but the following raises some more questions :

<?php

$test
= new \SplDoublyLinkedList;
$dataSet = [
[
'id' => 1],
[
'id' => 2],
[
'id' => 3],
[
'id' => 4],
];

foreach (
$dataSet as $row) {
$test->push($row);
}

echo
"count: " . $test->count() . PHP_EOL;
echo
"valid: " . ($test->valid() ? 'true' : 'false') . PHP_EOL;
echo
"current: " . var_export($test->current(), true) . PHP_EOL;
echo
"key: " . $test->key() . PHP_EOL;
echo
"1st shift: " . var_export($test->shift(), true) . PHP_EOL;
echo
"count: " . $test->count() . PHP_EOL;
echo
"valid: " . ($test->valid() ? 'true' : 'false') . PHP_EOL;
echo
"current: " . var_export($test->current(), true) . PHP_EOL;
echo
"key: " . $test->key() . PHP_EOL;
echo
"2nd shift: " . var_export($test->shift(), true) . PHP_EOL;
echo
"count: " . $test->count() . PHP_EOL;
echo
"valid: " . ($test->valid() ? 'true' : 'false') . PHP_EOL;
echo
"current: " . var_export($test->current(), true) . PHP_EOL;
echo
"key: " . $test->key() . PHP_EOL;
echo
"rewinding... " . PHP_EOL;
$test->rewind();
echo
"current: " . var_export($test->current(), true) . PHP_EOL;
echo
"2nd shift: " . var_export($test->shift(), true) . PHP_EOL;
echo
"count: " . $test->count() . PHP_EOL;
echo
"valid: " . ($test->valid() ? 'true' : 'false') . PHP_EOL;
echo
"current: " . var_export($test->current(), true) . PHP_EOL;
echo
"key: " . $test->key() . PHP_EOL;
?>

will result in :
<?php

/*
count: 4
valid: false <== First thing to note, you have no valid pointer unless you rewind first
current: NULL <== hence no current
key: 0 <== but we have a valid key
offsetGet(key): array ( <== indeed
'id' => 1,
)
1st shift: array ( <== and shift does return first row
'id' => 1,
)
count: 3 <== and count is maintained as expected
valid: false <== but internal pointer was left outside valid range
current: NULL <== hence no current again
key: 0 <== but we still have a valid key
offsetGet(key): array ( <== indeed
'id' => 2,
)
2nd shift: array ( <== and shift does return first row
'id' => 2,
)
count: 2 <== and count is maintained as expected
valid: false <== still not valid etc ..
current: NULL
key: 0
offsetGet(key): array (
'id' => 3,
)
rewinding... <== now rewind
current: array ( <== yay a current
'id' => 3,
)
3rd shift: array ( <== shift ok
'id' => 3,
)
count: 1 <== count ok
valid: true <== ouch valid
current: NULL <== with no current
key: 0 <== still our key is valid :o
offsetGet(key): array (
'id' => 4,
)
*/
?>

Conclusion : I may be missing something about why SplDoublyLinkedList::shift is not maintaining proper internal index in the first place, but I find it even more confusing to be able to end up with a valid valid() and a valid key() and no current() while there is obviously one.

Tested on php 5.6.30 & 7.1.2 with the exact same result.
To Top