Featured image of post A Bug Caused by Combined Array Index Changes and Reference Parameters in PHP

A Bug Caused by Combined Array Index Changes and Reference Parameters in PHP

PHP arrays are powerful but have hidden pitfalls

Today, our team encountered a bug reported in the group chat. After cloning the project locally, I spent some time reproducing the issue.


Code Overview

  1. The following code causes the first item removal to convert a Collection into an object (JSON data):
protected function transformJson($items)  
{  
    return Collection::make($items)  
-        ->values()  
        ->where('_remove_', '0')  
+        ->values()  
        ->map(fn($item) => Arr::except($item, '_remove_'))  
        ->toJson();  
  1. In the API data retrieval logic, this function call pattern caused issues:
public function index()  
{  
    // $json={"1":{"id": 2}}  
    $data = Collection::make($json);  
    // Filtering converts indexes to 0-based  
    $index = $this->getRandomAd($data, [1]);  

    // Returns null due to original key mismatch  
    return $data->get($index);  
}  

protected function getRandomAd(Collection $data, $notIn=[])  
{  
    $index = -1;  

    if (count($notIn) > 0) {  
        $data = $data->filter(fn($item) => !in_array($item['id'], $notIn))->values();  
    }  

    // Now working with 0-indexed array  
    foreach ($data as $index => $item) {  
        if ($item['id']) {  
            return $index;  
        }  
    }  

    // Returns filtered index incompatible with original collection  
    return $index;  
}  

Root Causes

Late-added filtering logic in getRandomAd unexpectedly converted the Collection to a 0-indexed array
Non-destructive operations (filter + values) created a new collection instead of modifying the original
Index mismatch occurred between the filtered 0-based indexes and original collection keys
Reference semantics were broken by reassignment rather than using mutable operations like transform

Key Insight: Using transform instead of map would have avoided this bug by modifying the original collection directly.