Sergey Neskhodovskiy
Sergey Neskhodovskiy

Reputation: 382

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']);

Upvotes: 1

Views: 2460

Answers (3)

Tudor
Tudor

Reputation: 1898

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) { ... });

Upvotes: 2

Alexey Mezenin
Alexey Mezenin

Reputation: 163798

Just tested it, this happens, because map() passes collection keys as third argument:

array_map($callback, $this->items, $keys);

So:

array_map('intval', ['3a', '4b'], [0, 1]); // Result is [3, 0]
array_map('intval', ['3a', '4b']); // Result is [3, 4]

Upvotes: 1

Shobi
Shobi

Reputation: 11461

if you try according to the laravel collection map syntax it yields the expected result

collect(['3a', '4b'])->map(function($item){
   return intval($item);
})->all();

Result

[3,4]

Upvotes: 1

Related Questions