Use concat() Instead of merge() When Combining Collections With Numeric Keys

πŸ“– 2 minutes read

This one has bitten me and probably every Laravel developer at least once. You’re combining two collections and items silently disappear. No error, no warning β€” just missing data.

The Trap

Laravel’s merge() and concat() look interchangeable at first glance. They’re not. The difference is all about how they handle numeric keys.

merge() overwrites values when keys match. concat() appends items regardless of keys.

$dbJobs = collect([
    0 => ['name' => 'Send Weekly Report', 'schedule' => '0 9 * * 1'],
    1 => ['name' => 'Clean Temp Files', 'schedule' => '0 0 * * *'],
]);

$configJobs = collect([
    0 => ['name' => 'Sync Inventory', 'schedule' => '*/30 * * * *'],
    1 => ['name' => 'Generate Invoices', 'schedule' => '0 6 * * 1'],
]);

// ❌ merge() - overwrites keys 0 and 1, you get 2 items instead of 4
$all = $dbJobs->merge($configJobs);
// Result: Sync Inventory, Generate Invoices (DB jobs silently lost!)

// βœ… concat() - appends all items, you get all 4
$all = $dbJobs->concat($configJobs);
// Result: Send Weekly Report, Clean Temp Files, Sync Inventory, Generate Invoices

Why This Is Sneaky

This bug is particularly nasty because it usually passes your tests. Test fixtures tend to have unique keys or small data sets that don’t overlap. It’s only in production β€” when two data sources happen to produce the same numeric indices β€” that items start vanishing.

And since there’s no error or exception, you won’t know anything is wrong until someone notices the missing data downstream.

The Rule of Thumb

If you’re combining two collections and you want all items from both, use concat(). Full stop.

Only use merge() when you specifically want the overwrite behavior β€” for example, merging config arrays where later values should replace earlier ones (the same way PHP’s array_merge() works with string keys).

Quick Reference

  • merge() β€” like array_merge(): string keys overwrite, numeric keys also overwrite (unlike native PHP!)
  • concat() β€” like array_push(): just appends everything, keys don’t matter
  • push() β€” adds a single item

One-line fix, saves you hours of debugging “where did my data go?”

Daryle De Silva

VP of Technology

11+ years building and scaling web applications. Writing about what I learn in the trenches.

Comments

Leave a Reply

Your email address will not be published. Required fields are marked *