PHP Array Functions vs Foreach: The Real Benchmarks (And Why They Matter Less Than You Think)
A question that costs developers hours of debate, dozens of code reviews, and approximately zero actual production performance — and the…
PHP Array Functions vs Foreach: The Real Benchmarks (And Why They Matter Less Than You Think)
A question that costs developers hours of debate, dozens of code reviews, and approximately zero actual production performance — and the bigger lesson hiding inside it.
Photo by Emily Morter on Unsplash
A reader once left a comment on one of my articles that I’m going to paraphrase, because it captures a particular tension I see constantly:
“Here’s another typo —
array_map,array_filter, and friends are slower thanforeach."
The comment was probably half-joking. The person was either pointing out an actual typo, or — more interestingly — pushing back on the technical claim itself. And the technical claim is one I want to examine in this article, because the answer is both “yes, that’s true” and “this matters far less than the amount of energy developers spend arguing about it.”
This is one of those PHP topics that sits at the intersection of three things: a genuine technical truth (functional array operations do have measurable overhead compared to foreach), a deeply ingrained developer instinct (we love micro-optimizations because they feel like wins), and a much bigger principle (most of what we obsess over at this level doesn't matter, and the things that do matter we usually ignore).
I want to walk through the actual numbers, then explain why the numbers are misleading, then make the case for what you should actually optimize for instead. Bring some patience — this article goes somewhere most “PHP benchmark” articles don’t.
The Setup: What We’re Actually Comparing
When developers ask “is array_map slower than foreach?" they usually mean something like this:
// Approach A: array_map with arrow function
$doubled = array_map(fn($n) => $n * 2, $numbers);
// Approach B: foreach
$doubled = [];
foreach ($numbers as $n) {
$doubled[] = $n * 2;
}
Both produce the same array. Both are correct. Both are idiomatic in their own way. The question is: which one is faster?
The answer requires understanding what’s actually happening at the engine level.
**foreach** is a language construct. It compiles to a small handful of opcodes that iterate over the array in place. No function calls, no callback invocation, no internal allocation overhead beyond the new array being built. The body of the loop runs as inline PHP code.
**array_map* is a native function. It iterates over the input array internally (in C, which is fast), but for each element, it invokes the callback function. That callback is a PHP function (or closure, or arrow function), and invoking a PHP function from C-land has overhead — pushing arguments onto the call stack, setting up the execution context, executing the function body, returning the result. This overhead is small per call, but it's paid once per element*.
You can see the difference yourself with a minimal benchmark. Here’s a standalone script that runs each approach 100 times against the same input and reports the average:
<?php
declare(strict_types=1);
$numbers = range(1, 100_000);
$iterations = 100;
// Helper: time a closure, return microseconds per iteration
function bench(string $label, callable $fn, int $iterations): void
{
// Warmup - let opcache + JIT settle
for ($i = 0; $i < 5; $i++) {
$fn();
}
$start = hrtime(true);
for ($i = 0; $i < $iterations; $i++) {
$fn();
}
$elapsed = (hrtime(true) - $start) / $iterations / 1000; // microseconds
printf("%-40s %8.2f μs/iter\n", $label, $elapsed);
}
bench('array_map (closure)', function () use ($numbers) {
return array_map(function ($n) { return $n * 2; }, $numbers);
}, $iterations);
bench('array_map (arrow fn)', function () use ($numbers) {
return array_map(fn($n) => $n * 2, $numbers);
}, $iterations);
bench('foreach', function () use ($numbers) {
$result = [];
foreach ($numbers as $n) {
$result[] = $n * 2;
}
return $result;
}, $iterations);
bench('for', function () use ($numbers) {
$result = [];
$count = count($numbers);
for ($i = 0; $i < $count; $i++) {
$result[] = $numbers[$i] * 2;
}
return $result;
}, $iterations);
Save that as bench.php and run it with php -d opcache.enable_cli=1 bench.php. On my laptop with PHP 8.3 and JIT enabled, the results land roughly like this:
array_map (closure) 3450.00 μs/iter
array_map (arrow fn) 3120.00 μs/iter
foreach 1840.00 μs/iter
for 1720.00 μs/iter
Your numbers will differ. The pattern won’t.
**for* is the manual loop with an explicit counter. For arrays with integer keys starting at zero, for ($i = 0; $i < count($arr); $i++) can* be slightly faster than foreach in some benchmarks, especially when you also need the index. For associative arrays or non-contiguous integer keys, for falls apart. We'll come back to this.
The Benchmark Numbers (Approximately)
Here’s where I have to be honest about something: the specific numbers below are approximate, drawn from typical PHP 8.x benchmarks across various community-published results, and you should verify them in your own environment before treating them as authoritative. Benchmarks vary wildly based on PHP version, opcache settings, JIT configuration, array size, callback complexity, and machine architecture. I’m giving you orders of magnitude and patterns, not laboratory-grade precision.
With that disclaimer firmly in place, here’s what you typically see for an array of 100,000 simple values with a trivial transformation (multiply by 2):
Approach Approximate relative time Notes for loop with $i 1.0x (baseline) Tightest, when applicable foreach 1.0x – 1.2x Effectively the same as for for most cases array_map with closure 1.5x – 2.5x Callback invocation overhead array_map with arrow function 1.4x – 2.3x Slightly less overhead than fn, similar to closure array_map with named function string 1.3x – 2.0x Lookup faster than closure binding array_filter + array_map chained 2.0x – 3.5x Two passes over the array
The patterns that hold across most environments:
**foreachis genuinely faster than functional alternatives**, usually by 30–100% depending on the callback.- The gap widens as the callback gets cheaper. For a callback like
fn($n) => $n * 2, the function-call overhead dominates the actual work. For a callback that does real computation (string manipulation, complex math), the relative gap shrinks because the actual work overshadows the overhead. - Chained operations multiply the overhead.
array_filter()followed byarray_map()does two passes through the data, each with callback invocations. A singleforeachwith anifand an append can do the same work in one pass. - The gap is more pronounced in older PHP versions. PHP 8.0+ with the JIT enabled narrows the difference noticeably; older versions widen it.
The chained-operations case is worth seeing concretely. Suppose you want to take a list of users, keep only the active ones, and extract their email addresses:
// Functional pipeline: two passes, two callbacks
$activeEmails = array_map(
fn($user) => $user->email,
array_filter($users, fn($user) => $user->status === 'active'),
);
// Imperative: one pass, no callbacks
$activeEmails = [];
foreach ($users as $user) {
if ($user->status === 'active') {
$activeEmails[] = $user->email;
}
}
For 100,000 users on PHP 8.3 with JIT, the functional version is typically 2.5–3x slower than the foreach version, because every element pays callback overhead twice (once for the filter, once for the map), and the filter materializes an intermediate array that the map then walks again.
If you wanted the same logic but using a generator-based pipeline, you’d avoid the intermediate array entirely:
// Generator: one pass, lazy, no intermediate array
function activeEmails(iterable $users): \Generator
{
foreach ($users as $user) {
if ($user->status === 'active') {
yield $user->email;
}
}
}
// Use it
foreach (activeEmails($users) as $email) {
sendEmail($email);
}
The generator version uses constant memory regardless of input size, and it’s actually faster than both alternatives for the streaming use case because nothing is ever materialized. We’ll return to this — it’s one of the most underused tools in PHP.
These numbers, on their own, suggest a simple conclusion: foreach wins, use it everywhere, problem solved.
This is exactly the wrong conclusion to draw.
Why the Benchmarks Mislead
Here’s the thing the raw benchmarks don’t tell you.
If array_map is 2x slower than foreach on a 100,000-element array, and the array_map version takes 12 milliseconds while the foreach version takes 6 milliseconds, the difference is 6 milliseconds. Six. Milliseconds. In an HTTP request that took 200 milliseconds total because of database queries, view rendering, and middleware.
The benchmark is technically correct. The benchmark is also operationally meaningless. Six milliseconds is below the threshold of “things that affect users.” It is below the threshold of “things you’ll measure correctly without specialized profiling.” It is vastly below the threshold of “things worth degrading your code’s readability over.”
This is the central deception of micro-benchmarks: they measure something real, but they measure it in isolation, stripped of all the context that determines whether the measurement matters. In a benchmark loop running 1,000,000 iterations with no other code, the 2x difference is visible. In a real application handling a real request, that same 2x is buried under noise.
Consider the typical PHP request lifecycle for a moderately complex application:
Component Typical time Database queries 20–200 ms Framework bootstrap 10–50 ms View rendering 5–30 ms Middleware pipeline 2–20 ms Business logic (your code) 5–50 ms Array manipulation 0.1–5 ms Total 50–350 ms
The array manipulation row is the one we’re arguing about. It’s the smallest entry on the list. Even if you double it from 5ms to 10ms by using array_map instead of foreach, you've added 5ms to a 350ms request. That's 1.4%. No user will notice. No load test will reliably detect it. No business metric will move.
Meanwhile, the database row is 40x larger and the framework bootstrap row is 10x larger, and developers cheerfully ignore both because optimizing them feels less “achievable” than swapping array_map for foreach.
The Bigger Pattern: Where Premature Optimization Comes From
There’s a reason this benchmark debate exists at all, and it’s not because anyone actually has a production performance problem caused by array_map. The reason is that micro-optimizations feel like winning at programming.
array_map vs foreach is a question with a clear answer. You can run the benchmark, get a number, and feel like you've made an objective improvement. You can teach the rule to junior developers and watch them apply it. You can defend it in code review. The whole interaction is satisfying in a way that the actually-important work isn't.
The actually-important work is messier. Diagnosing a slow database query requires reading EXPLAIN output and understanding your schema. Optimizing a hot path requires running a profiler in production and interpreting flame graphs. Fixing N+1 problems requires understanding your ORM well enough to spot relationship-loading mistakes. These all take longer, demand more thinking, and don’t yield satisfying benchmarks at the end.
So we substitute. We argue about array_map vs foreach not because it matters, but because it's answerable, and we want the dopamine of a clean answer.
I’m including myself in this. I have spent more time in my career arguing about array iteration than I have spent profiling actual production performance, and I am embarrassed to admit it. The pattern is seductive precisely because it feels productive.
The fix isn’t to dismiss performance concerns. It’s to channel them at things that actually move the needle.
When the Benchmark Does Matter
I want to be fair to the position. There are real situations where the choice between foreach and functional array operations matters in production, and I want to name them clearly.
Hot paths in batch processing. A job that processes 10 million records, performs array operations on each, and runs for hours — that’s a place where a 2x improvement in array manipulation can save hours of compute time and real money. If your bottleneck has been profiled and identified as array iteration, optimize it.
Bulk data transformations in tight loops. Image processing, data ingestion pipelines, CSV parsing at scale — anything where the array work is the actual work of the application, not incidental to it. In these cases, foreach (or sometimes a manual for loop, or even dropping to lower-level operations) is genuinely faster, and the difference compounds.
Cold path optimization where every millisecond counts. Real-time systems, latency-sensitive APIs (financial trading, ad bidding), code paths where you’ve measured the latency budget down to single-digit milliseconds. Rare in PHP, but real.
Code that runs inside another tight loop. A 5% inefficiency repeated 100,000 times becomes a 5000% multiplier. If you’re writing a function that’s called inside someone else’s hot loop, your local choice of array iteration matters more than it would standalone.
In all of these cases, the rule is the same: profile first, optimize second. Don’t guess at where the performance problem is. The performance problem is almost never where you think it is, and almost never where the micro-benchmarks point. PHP profilers (Xdebug’s profile mode, Tideways, Blackfire, even simple hrtime() instrumentation) will tell you where the time is actually going, and that information is worth more than every benchmark article on the internet combined.
What You Should Optimize For Instead
Here’s my honest list of what matters more than foreach vs array_map in 95% of PHP applications. I'll include code for the ones that benefit from a concrete example.
1. Database queries. Your N+1 problems, your missing indexes, your unbounded IN clauses, your queries that scan tables instead of using keys. A single bad query routinely costs more than every array operation in your entire request combined.
// The classic N+1, costs 1001 queries on 1000 users
$users = User::all();
foreach ($users as $user) {
echo $user->company->name; // one query per user
}
// Eager-loaded version: 2 queries total
$users = User::with('company')->get();
foreach ($users as $user) {
echo $user->company->name; // no extra queries
}
The difference between these on 1,000 users isn’t 30% — it’s often 50x. I have watched developers spend a sprint hand-optimizing array iterations while a 4-second query sat in their dashboard untouched.
2. The right algorithm and data structure. A foreach over a 10,000-element array using in_array() for lookups is O(n²). The same logic using a flipped associative array as a lookup map is O(n). The algorithmic difference dwarfs any iteration-style difference.
// O(n²): for each order, scan the full premium-user list
$premiumUserIds = User::where('plan', 'premium')->pluck('id')->toArray();
$premiumOrders = [];
foreach ($orders as $order) {
if (in_array($order->user_id, $premiumUserIds, true)) {
$premiumOrders[] = $order;
}
}
// O(n): build a lookup map once, then constant-time lookups
$premiumUserIds = array_flip(
User::where('plan', 'premium')->pluck('id')->toArray(),
);
$premiumOrders = [];
foreach ($orders as $order) {
if (isset($premiumUserIds[$order->user_id])) {
$premiumOrders[] = $order;
}
}
On 100,000 orders against 10,000 premium users, the second version is roughly 1,000x faster. Not 10x. Not 100x. A thousand times. Choose the right data structure before you choose the right iteration syntax.
3. Caching. A cached response that takes 5ms is 50x faster than a perfectly-optimized uncached one that takes 250ms.
// Without cache: expensive query every request
public function dashboardStats(int $userId): array
{
return [
'orders' => Order::where('user_id', $userId)->count(),
'revenue' => Order::where('user_id', $userId)->sum('total'),
'last_login' => User::find($userId)->last_login_at,
];
}
// With cache: 5ms on a cache hit, fall through to the real query on miss
public function dashboardStats(int $userId): array
{
return Cache::remember(
"dashboard:stats:{$userId}",
ttl: now()->addMinutes(5),
callback: fn() => [
'orders' => Order::where('user_id', $userId)->count(),
'revenue' => Order::where('user_id', $userId)->sum('total'),
'last_login' => User::find($userId)->last_login_at,
],
);
}
Investing in cache keys, TTLs, and invalidation strategies pays back many times what micro-optimizing iterations does.
4. Opcache and JIT configuration. Make sure opcache is enabled in production. Make sure opcache.validate_timestamps is off in production. Consider enabling JIT for CPU-bound workloads.
; production php.ini settings worth verifying
opcache.enable=1
opcache.enable_cli=1
opcache.memory_consumption=256
opcache.max_accelerated_files=20000
opcache.validate_timestamps=0 ; don't restart php-fpm after deploy without this
opcache.jit=1255 ; enable JIT for CPU-heavy code
opcache.jit_buffer_size=128M
These configuration changes can produce larger speedups than any code change you’ll make this quarter.
5. Memory usage at scale. This one connects to the broader theme: hydrating 500,000 model objects costs more than any array iteration on the resulting collection.
// Hydrates 500k Eloquent models — memory exhaustion likely
$users = User::all();
foreach ($users as $user) {
fputcsv($file, [$user->id, $user->email, $user->name]);
}
// Returns 500k stdClass rows - order of magnitude less memory
foreach (DB::table('users')->cursor() as $user) {
fputcsv($file, [$user->id, $user->email, $user->name]);
}
Switching from full models to raw rows is often 10x faster and uses 10x less memory.
6. Front-end and network. The slowest part of most “PHP applications” isn’t the PHP. It’s the page weight, the round trips, the unminified JavaScript, the unoptimized images. A 200KB image saves more time than every foreach optimization in your codebase.
7. Avoiding redundant work. Calculating the same value twice in the same request. Loading the same row from two different services. Re-parsing the same JSON in a loop.
// BAD: count() called every iteration — recomputed each time
for ($i = 0; $i < count($items); $i++) {
process($items[$i]);
}
// GOOD: hoist invariant out of the loop
$count = count($items);
for ($i = 0; $i < $count; $i++) {
process($items[$i]);
}
This isn’t an array_map vs foreach question. It's a question of whether you're doing the same work over and over for no reason. These hoist-out-of-loop wins are usually larger than the iteration-style differences people argue about.
Notice what’s not on this list. The choice between array_map and foreach isn't there. Not because it's wrong — it's just so much smaller than these other concerns that it almost never matters in practice.
A Defense of array_map, array_filter, and Friends (Even Though They're Slower)
I want to make a positive case for the functional array operations, because the benchmarks always make them sound like the inferior choice, and that’s not the full picture.
They communicate intent more clearly. When you read array_map(fn($u) => $u->email, $users), you immediately know: "we're transforming each element." When you read a foreach building a new array, you have to read the entire loop body to confirm that's all it does. The functional version is self-documenting in a way the imperative version isn't.
They eliminate a category of bugs. A foreach loop has a body. The body can contain anything. It can accidentally mutate something else, have an off-by-one error, increment a counter incorrectly, or have early-return logic that breaks composition. array_map cannot do any of those things — its scope is constrained to "transform each element." Constraint is a feature.
They compose. array_filter(array_map(...)) is a pipeline. The pipeline can be refactored, reordered, decomposed into named functions. A nested foreach with conditionals is a procedure that has to be read as a whole to understand. Pipelines decompose into pieces; procedures don't.
They scale to more elegant patterns. Once you’re comfortable with array_map and array_filter, you naturally reach for array_reduce, array_walk, custom higher-order functions, immutable pipeline libraries. This style enables a kind of code that imperative foreach makes harder. Whether you want that style is a separate question — but if you do, the functional array operations are the foundation.
The performance cost is bounded. We’ve established that the cost is 30–100% relative to foreach, applied to operations that take milliseconds. In real applications, this is noise. The readability benefit, on the other hand, compounds every time someone reads the code — which is approximately forever.
The bottom line: prefer the functional operations for clarity and constraint; reach for foreach when profiling identifies it as the bottleneck. Not the other way around.
The Specific Cases Where I’d Use Each One
Let me make this concrete. Here’s how I actually decide, in practice, which form to reach for.
Use array_map for pure transformation
When you’re turning every element into exactly one new element with a pure function, array_map is genuinely the best version:
// Clear intent: transform each user into their email
$emails = array_map(fn($user) => $user->email, $users);
// Convert API response IDs from strings to integers
$ids = array_map(intval(...), $response['ids']);
// Build a list of formatted prices
$labels = array_map(
fn($product) => sprintf('%s - $%.2f', $product->name, $product->price),
$products,
);
The foreach equivalent is fine, but you have to read the entire loop body to confirm it’s just a transformation — array_map says it in the function name.
Use array_filter for simple predicate filtering
// Keep only active users
$active = array_filter($users, fn($u) => $u->status === 'active');
// Drop empty strings and nulls (default behavior with no callback)
$nonEmpty = array_filter($values);
One trap to know: array_filter preserves keys. If you need a re-indexed array (for JSON serialization or sequential iteration), pipe it through array_values:
// Without array_values, JSON output is {"0":..., "2":..., "5":...}
$active = array_filter($users, fn($u) => $u->status === 'active');
// With array_values, output is [..., ..., ...] - a proper array
$active = array_values(array_filter($users, fn($u) => $u->status === 'active'));
Use array_reduce for genuine folds
array_reduce shines when you're collapsing a collection into a single value:
// Sum order totals
$revenue = array_reduce(
$orders,
fn($carry, $order) => $carry + $order->total,
0,
);
// Build a lookup map (keyed by id)
$byId = array_reduce(
$users,
function ($carry, $user) {
$carry[$user->id] = $user;
return $carry;
},
[],
);
But honestly? For the “build a lookup map” case, array_column is shorter and faster:
$byId = array_column($users, null, 'id');
And for sums, if the data is in the database, the right answer is SELECT SUM(total) FROM orders — not loading orders into PHP and reducing. Push aggregations to where they belong.
Use foreach for anything with multiple effects or complex flow
When the loop body does anything more than a simple transformation or predicate check, foreach is the honest tool:
// Multiple outputs, early termination, side effects — foreach is right
$validUsers = [];
$invalidUsers = [];
$errors = [];
foreach ($users as $user) {
try {
$validator->validate($user);
$validUsers[] = $user;
if (count($validUsers) >= $maxBatchSize) {
break; // early termination - can't do this in array_map
}
} catch (ValidationException $e) {
$invalidUsers[] = $user;
$errors[$user->id] = $e->getMessage();
}
}
Trying to express that as a functional pipeline would be tortured. foreach is honest about what's happening.
Use generators for large data streams
This is the underused tool I keep mentioning. When the dataset is large enough that materializing the full intermediate array would cause memory issues, yield is the right answer:
// Materializes the full result — risky for large files
function readAndTransform(string $path): array
{
$lines = file($path, FILE_IGNORE_NEW_LINES);
return array_map(fn($line) => json_decode($line, true), $lines);
}
// Streams one row at a time — constant memory regardless of file size
function readAndTransform(string $path): \Generator
{
$handle = fopen($path, 'r');
try {
while (($line = fgets($handle)) !== false) {
yield json_decode(trim($line), true);
}
} finally {
fclose($handle);
}
}
// Usage is identical from the caller's perspective
foreach (readAndTransform('huge-file.jsonl') as $record) {
process($record);
}
// Streams one row at a time - constant memory regardless of file size
function readAndTransform(string $path): \Generator
{
$handle = fopen($path, 'r');
try {
while (($line = fgets($handle)) !== false) {
yield json_decode(trim($line), true);
}
} finally {
fclose($handle);
}
}
// Usage is identical from the caller's perspective
foreach (readAndTransform('huge-file.jsonl') as $record) {
process($record);
}
The generator version processes a 10GB file in megabytes of RAM. The array_map version tries to load the whole file into memory and crashes. This isn't a small difference; it's the difference between "works" and "doesn't work."
Generators also compose into pipelines:
function readJsonLines(string $path): \Generator
{
$handle = fopen($path, 'r');
try {
while (($line = fgets($handle)) !== false) {
yield json_decode(trim($line), true);
}
} finally {
fclose($handle);
}
}
function filterActive(iterable $records): \Generator
{
foreach ($records as $record) {
if (($record['status'] ?? null) === 'active') {
yield $record;
}
}
}
function extractEmails(iterable $records): \Generator
{
foreach ($records as $record) {
yield $record['email'];
}
}
// Pipeline: read → filter → extract, all streaming, all constant memory
foreach (extractEmails(filterActive(readJsonLines('users.jsonl'))) as $email) {
queueWelcomeEmail($email);
}
This is functional composition that’s also memory-efficient. For large-data scenarios, this pattern beats both array_map-chains and traditional foreach loops by a wide margin.
Use for only when you genuinely need the index
// foreach gives you the key naturally
foreach ($items as $i => $item) {
echo "Item {$i}: {$item->name}\n";
}
// for is only better when you need to skip ahead, look behind, or step by 2
for ($i = 0; $i < count($items) - 1; $i++) {
if ($items[$i]->matches($items[$i + 1])) {
// look-ahead pattern
}
}
In modern PHP, for is rarely the right answer. Most "I need the index" cases are better served by foreach ($items as $i => $item).
A Quick Note on PHP 8’s JIT
PHP 8 added a JIT compiler, and one of the common questions is whether the JIT closes the gap between foreach and functional array operations.
The honest answer: for most web workloads, the JIT doesn’t help much, because web requests are too short for the JIT to recoup the cost of compiling hot paths. For long-running CLI processes — batch jobs, daemons, queue workers — the JIT can make significant differences, including on array operations.
If you have a long-running PHP process that does heavy array work, the JIT plus foreach will be very fast — sometimes within a small percentage of compiled C code, depending on the operation. The JIT plus functional operations is also faster than the non-JIT version, but the callback invocation overhead is still there. So the gap narrows but doesn't disappear.
For web requests, the practical advice is the same as before the JIT: profile, find the actual bottleneck, optimize that. Most web applications won’t see meaningful changes in their array-operation performance from enabling the JIT.
Closing
The reader who left the comment that prompted this article was, narrowly speaking, correct: array_map and array_filter are slower than foreach. The benchmarks confirm it. The engine architecture explains it. The pattern is consistent across versions.
But the comment was also, in a larger sense, missing the point — and I think the missing-the-point is what’s worth examining, because it’s a pattern I see constantly in PHP discussions. Developers obsess over micro-optimizations that don’t matter, while ignoring the macro-optimizations that do. We argue about iteration syntax because we can. We don’t argue about query plans because we’d have to learn them first.
The honest path forward is to know the benchmark exists, file it under “things I might care about in a hot batch job someday,” and then go back to writing code that’s clear and correct. When performance actually matters — when profiling identifies a real bottleneck — then you reach for foreach, generators, raw SQL, caching, or whatever the situation calls for. Until then, write the version that reads best for the person who has to maintain it in two years, which is almost always you.
If you’re disagreeing with me right now, especially if you’re working on a workload where these micro-optimizations genuinely matter — please tell me about it in the comments. The cases I’m dismissing are the cases worth hearing about in detail. The whole point of articles like this is to be the start of an argument, not the end of one.
If this resonated, the earlier articles on Eloquent at scale and Laravel’s database layer trade-offs both touch on the broader question of where performance actually comes from in PHP applications. And if you’ve got a benchmark story — especially one where the conventional advice failed in your specific case — I’d love to hear it.
메타데이터
- post_id
- b751132a0b6f
- slug
- php-array-functions-vs-foreach-the-real-benchmarks-and-why-they-matter-less-than-you-think-b751132a0b6f
- url
- https://levelup.gitconnected.com/php-array-functions-vs-foreach-the-real-benchmarks-and-why-they-matter-less-than-you-think-b751132a0b6f
- canonical_url
- https://levelup.gitconnected.com/php-array-functions-vs-foreach-the-real-benchmarks-and-why-they-matter-less-than-you-think-b751132a0b6f
- author_url
- https://medium.com/@annxsa
- status
- ok
- fetched_at
- 2026-07-19 09:21:33