Be Careful with array_merge() and Numeric Keys in PHP

array_merge() reindexes numeric keys, which can silently break associative arrays that use IDs as keys.

I recently ran into a bug caused by array_merge().

I had an array that mapped delivery order IDs to sales order IDs:

[
    1205 => 4727,
    1208 => 4731,
]

To merge new data with the existing cache, I wrote:

try {
    $existing = Cache::get($cache_key, []);

    $merged = array_merge($delivery_orders_to_approve, $existing);

    Cache::put($cache_key, $merged, ProcessingService::BATCH_CACHE_SECONDS);
} finally {
    $lock->release();
}

The problem? array_merge() reindexes numeric keys.

Instead of:

[
    1205 => 4727,
    1208 => 4731,
]

I got:

[
    0 => 4727,
    1 => 4731,
]

Since the delivery order ID was stored as the array key, the mapping was lost and the next process always picked the wrong delivery order.

The fix was to use array_replace() instead:

$merged = array_replace(
    $existing,
    $delivery_orders_to_approve,
);

Or, if you want to keep the left-hand values when duplicate keys exist:

$merged = $delivery_orders_to_approve + $existing;

Preserve ID Keys with the Right Array Operation

Use array_merge() for lists, not associative arrays whose numeric keys carry meaning.

When those keys are IDs, use array_replace() if later values should overwrite existing values, or the array union operator (+) if existing values should win.

PHP Documents This Behavior

The PHP documentation explicitly mentions this behavior:

Values in the input arrays with numeric keys will be renumbered with incrementing keys starting from zero in the result array.