PHP 8.5's array_first and array_last: Finally, Native Array Helpers We Can Use.
5 minutes
Right, let's talk about something that's been bugging us for years. If you've been writing PHP for any length of time, you've probably written some variation of "get the first item from this array" more times than you'd care to admit. And if you're a Laravel developer like us, you've probably been spoilt by the Arr::first()
and Arr::last()
helpers that make this dead simple.
Well, PHP 8.5 is finally catching up, and honestly, it's about bloody time.
The Array Access Dance We've All Done
Before we get into the new stuff, let's be honest about how we've been handling this in vanilla PHP up until now. Need the first element of an array? You've got options, none of them particularly elegant:
1<?php 2 3// Option 1: reset() - but it messes with the internal pointer 4$array = ['apple', 'banana', 'cherry']; 5$first = reset($array); // 'apple' 6 7// Option 2: array_values() with index access - creates a whole new array 8$first = array_values($array)[0]; // 'apple' 9 10// Option 3: array_key_first() - verbose and not intuitive11$first = $array[array_key_first($array)]; // 'apple'12 13// Option 4: array_shift() - but it modifies your array!14$first = array_shift($array); // 'apple' (and $array is now ['banana', 'cherry'])
None of these feel quite right, do they? They either have side effects, create unnecessary overhead, or just look awkward. It's one of those things that makes you wonder why PHP didn't have a simple solution from the start.
Enter Laravel's Helpers (Our current Safety Blanket)
This is exactly why we've been reaching for Laravel's array helpers for years. If you're working in Laravel, this has been your reality:
1<?php 2 3use Illuminate\Support\Arr; 4 5$array = ['apple', 'banana', 'cherry']; 6$first = Arr::first($array); // 'apple' 7$last = Arr::last($array); // 'cherry' 8 9// Or with the global helper10$first = head($array); // 'apple'11$last = last($array); // 'cherry'
Clean, simple, no side effects. It just works. We've been using these helpers so much that writing vanilla PHP without them feels like coding with one hand tied behind your back.
PHP 8.5 to the Rescue
Finally, with PHP 8.5, we're getting native array_first()
and array_last()
functions. Here's what they look like:
1<?php 2 3$array = ['apple', 'banana', 'cherry']; 4$first = array_first($array); // 'apple' 5$last = array_last($array); // 'cherry' 6 7// Works with associative arrays too 8$user = ['name' => 'John', 'email' => 'john@example.com', 'age' => 30]; 9$first = array_first($user); // 'John'10$last = array_last($user); // 3011 12// Empty arrays return null13$first = array_first([]); // null14$last = array_last([]); // null
Simple, intuitive, and exactly what we've been waiting for. No internal pointer shenanigans, no array copying, no weird syntax. Just straightforward functions that do what they say on the tin.
The Migration Path (Or: Saying Goodbye to Our Helpers)
Now here's where it gets interesting for us as Laravel developers. Once PHP 8.5 becomes our minimum version (which, let's be realistic, won't be for a while), we can start replacing those Laravel helpers with native PHP functions.
Here's what that migration might look like:
1<?php 2 3// Before (Laravel helper) 4use Illuminate\Support\Arr; 5 6$firstUser = Arr::first($users); 7$lastOrder = Arr::last($orders); 8 9// After (PHP 8.5 native)10$firstUser = array_first($users);11$lastOrder = array_last($orders);
But wait, there's a catch. Laravel's Arr::first()
and Arr::last()
helpers actually do a bit more than just grab the first or last element. They can also accept a callback:
1<?php 2 3// Laravel's Arr::first with callback 4$firstAdmin = Arr::first($users, function ($user) { 5 return $user->role === 'admin'; 6}); 7 8// PHP 8.5's array_first doesn't support this 9// You'll need to filter first10$admins = array_filter($users, fn($user) => $user->role === 'admin');11$firstAdmin = array_first($admins);
So it's not quite a drop-in replacement for all use cases. Classic PHP, eh?
Performance Considerations
One thing we were curious about was performance. After all, if these new functions are just syntactic sugar over existing functionality, what's the point?
Well, the good news is that array_first()
and array_last()
are implemented at the C level, which means they're fast. They're essentially doing this under the hood:
1<?php 2 3// Simplified implementation 4function array_first(array $array): mixed { 5 return $array === [] ? null : $array[array_key_first($array)]; 6} 7 8function array_last(array $array): mixed { 9 return $array === [] ? null : $array[array_key_last($array)];10}
But because they're native functions, they avoid the overhead of user-land function calls. In our testing (yes, we're that nerdy), we found them to be marginally faster than the equivalent PHP implementations, especially when called frequently.
The Polyfill Strategy
If you're itching to use these functions now but can't upgrade to PHP 8.5 yet (and let's face it, most of us can't), there's a polyfill available:
1composer require polyfills/array-first-array-last
Or you can roll your own:
1<?php 2 3if (!function_exists('array_first')) { 4 function array_first(array $array): mixed { 5 return $array === [] ? null : $array[array_key_first($array)]; 6 } 7} 8 9if (!function_exists('array_last')) {10 function array_last(array $array): mixed {11 return $array === [] ? null : $array[array_key_last($array)];12 }13}
We've actually started using the polyfill in some of our newer projects where we want to write "future PHP" but are stuck on 8.4 for now. It's a nice way to prepare your codebase for the eventual upgrade.
The Verdict
Look, these aren't revolutionary functions that will transform how we write PHP. But they're exactly the kind of quality-of-life improvements that make the language more pleasant to work with. No more explaining to junior developers why reset()
affects the array pointer, no more reaching for Laravel helpers for basic array operations.
Are they worth upgrading to PHP 8.5 for? On their own, probably not. But combined with the other improvements coming in 8.5 (like the pipe operator we wrote about recently), they're part of a broader trend of PHP becoming more developer-friendly.
For us at Jump24, we're looking forward to the day when we can use these natively across all our projects. Until then, we'll keep our Laravel helpers close and our polyfills closer.
What About Your Projects?
We're curious - how often do you find yourself needing to grab the first or last element of an array? Are you using Laravel's helpers, or have you been making do with PHP's existing functions? And more importantly, are you as excited about these small improvements as we are, or are we just PHP nerds getting worked up over nothing?
Drop us a line or tweet at us - we'd love to hear how other teams are handling this transition!
Looking for help with a PHP Project?
Talk to us today about our Team Augmentation service to see how we can help you with your current PHP Project.