Skip to content

Commit ab1145e

Browse files
committed
[RFC] Implement array_first() and array_last()
1 parent cb4bafa commit ab1145e

File tree

7 files changed

+125
-1
lines changed

7 files changed

+125
-1
lines changed

NEWS

+1
Original file line numberDiff line numberDiff line change
@@ -211,6 +211,7 @@ PHP NEWS
211211
(Michael Orlitzky).
212212
. Fixed bug GH-18062 (is_callable(func(...), callable_name: $name) for first
213213
class callables returns wrong name). (timwolla)
214+
. Added array_first() and array_last(). (nielsdos)
214215

215216
- Streams:
216217
. Fixed bug GH-16889 (stream_select() timeout useless for pipes on Windows).

UPGRADING

+4
Original file line numberDiff line numberDiff line change
@@ -356,6 +356,10 @@ PHP 8.5 UPGRADE NOTES
356356
. ReflectionConstant::getAttributes() was introduced.
357357
RFC: https://wiki.php.net/rfc/attributes-on-constants
358358

359+
- Standard:
360+
. Added array_first() and array_last().
361+
RFC: https://wiki.php.net/rfc/array_first_last
362+
359363
========================================
360364
7. New Classes and Interfaces
361365
========================================

ext/standard/array.c

+26
Original file line numberDiff line numberDiff line change
@@ -4513,6 +4513,32 @@ PHP_FUNCTION(array_key_last)
45134513
}
45144514
/* }}} */
45154515

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

ext/standard/basic_functions.stub.php

+10
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

+11-1
Some generated files are not rendered by default. Learn more about customizing how changed files appear on GitHub.
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: {}
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)