phplaravellaravel-collection

Why is laravel collection mapping array elements differently?


Using Laravel version 5.4.

Code:

collect(['3a', '4b'])->map('intval')->all();

Expected result: [3, 4]

But instead the line above returns [3, 0] - i.e. the first element is transformed correctly, while the second isn't?

What's happening here?

Noteworthy, I'm getting the correct result with the native php array_map function:

// returns [3, 4]
array_map('intval', ['3a', '4b']);

Solution

  • In order to understand exactly what is happening we can check the Collection class source code where we find the map function

    public function map(callable $callback)
    {
        $keys = array_keys($this->items);
    
        $items = array_map($callback, $this->items, $keys);
    
        return new static(array_combine($keys, $items));
    }
    

    So what laravel does it actually adds the keys as well to the array_map function call, which ultimately produces this call array_map('intval', ['3a', '4b'], [0, 1])

    This will call intval('3a', 0) and intval('4b', 1) respectively, which as expected will yield 3 and 0, because the second parameter of intval according to the official PHP docs is actually the base.

    Laravel adds the keys because sometimes you might use them in your map callback as such

    $collection->map(function($item, $key) { ... });