Skip to content

Commit 264d60a

Browse files
committed
[RFC] Implement array_first() and array_last()
1 parent ce3d1cd commit 264d60a

File tree

5 files changed

+120
-1
lines changed

5 files changed

+120
-1
lines changed

ext/standard/array.c

Lines changed: 26 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -4511,6 +4511,32 @@ PHP_FUNCTION(array_key_last)
45114511
}
45124512
/* }}} */
45134513

4514+
PHP_FUNCTION(array_first)
4515+
{
4516+
HashTable *array;
4517+
4518+
ZEND_PARSE_PARAMETERS_START(1, 1)
4519+
Z_PARAM_ARRAY_HT(array)
4520+
ZEND_PARSE_PARAMETERS_END();
4521+
4522+
ZEND_HASH_FOREACH_VAL(array, zval *zv) {
4523+
RETURN_COPY_DEREF(zv);
4524+
} ZEND_HASH_FOREACH_END();
4525+
}
4526+
4527+
PHP_FUNCTION(array_last)
4528+
{
4529+
HashTable *array;
4530+
4531+
ZEND_PARSE_PARAMETERS_START(1, 1)
4532+
Z_PARAM_ARRAY_HT(array)
4533+
ZEND_PARSE_PARAMETERS_END();
4534+
4535+
ZEND_HASH_REVERSE_FOREACH_VAL(array, zval *zv) {
4536+
RETURN_COPY_DEREF(zv);
4537+
} ZEND_HASH_FOREACH_END();
4538+
}
4539+
45144540
/* {{{ Return just the values from the input array */
45154541
PHP_FUNCTION(array_values)
45164542
{

ext/standard/basic_functions.stub.php

Lines changed: 10 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1712,6 +1712,16 @@ function array_key_first(array $array): int|string|null {}
17121712
*/
17131713
function array_key_last(array $array): int|string|null {}
17141714

1715+
/**
1716+
* @compile-time-eval
1717+
*/
1718+
function array_first(array $array): mixed {}
1719+
1720+
/**
1721+
* @compile-time-eval
1722+
*/
1723+
function array_last(array $array): mixed {}
1724+
17151725
/**
17161726
* @return array<int, mixed|ref>
17171727
* @compile-time-eval

ext/standard/basic_functions_arginfo.h

Lines changed: 11 additions & 1 deletion
Some generated files are not rendered by default. Learn more about customizing how changed files appear on GitHub.
Lines changed: 53 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,53 @@
1+
--TEST--
2+
array_first()/array_last()
3+
--FILE--
4+
<?php
5+
$str = "hello world";
6+
7+
$test_cases = [
8+
["single element"],
9+
[&$str, 1],
10+
[1, &$str],
11+
[1 => 1, 0 => 0, 3 => 3, 2 => 2],
12+
[100 => []],
13+
[new stdClass, false],
14+
[true, new stdClass],
15+
];
16+
17+
foreach ($test_cases as $test_case) {
18+
// Output the checked values
19+
echo "--- Testing: ", json_encode($test_case), " ---\n";
20+
echo "First: ", json_encode(array_first($test_case)), "\n";
21+
echo "Last: ", json_encode(array_last($test_case)), "\n";
22+
23+
// Sanity check consistency with array_key_first()/array_key_last()
24+
if (array_first($test_case) !== $test_case[array_key_first($test_case)]) {
25+
throw new Error("Key first and value first inconsistency");
26+
}
27+
if (array_last($test_case) !== $test_case[array_key_last($test_case)]) {
28+
throw new Error("Key last and value last inconsistency");
29+
}
30+
}
31+
?>
32+
--EXPECT--
33+
--- Testing: ["single element"] ---
34+
First: "single element"
35+
Last: "single element"
36+
--- Testing: ["hello world",1] ---
37+
First: "hello world"
38+
Last: 1
39+
--- Testing: [1,"hello world"] ---
40+
First: 1
41+
Last: "hello world"
42+
--- Testing: {"1":1,"0":0,"3":3,"2":2} ---
43+
First: 1
44+
Last: 2
45+
--- Testing: {"100":[]} ---
46+
First: []
47+
Last: []
48+
--- Testing: [{},false] ---
49+
First: {}
50+
Last: false
51+
--- Testing: [true,{}] ---
52+
First: true
53+
Last: {}
Lines changed: 20 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,20 @@
1+
--TEST--
2+
array_first()/array_last() error cases
3+
--FILE--
4+
<?php
5+
var_dump(array_first([]));
6+
var_dump(array_last([]));
7+
8+
$array = [1, 2, 3];
9+
unset($array[0]);
10+
unset($array[1]);
11+
unset($array[2]);
12+
13+
var_dump(array_first($array));
14+
var_dump(array_last($array));
15+
?>
16+
--EXPECT--
17+
NULL
18+
NULL
19+
NULL
20+
NULL

0 commit comments

Comments
 (0)