Laravel collection incrementing inside map not possible with arrow function

Viewed 695

I'm trying to increment during the map method, however my variable doesn't seem to save the new value. My code:

$position = 0;

$statement = $medias->map(fn(string $media) => [
                'position' => ++$position
            ])->values();

My expected result would be:

#items: array:4 [
    0 => array:4 [
      "position" => 1
    ]
    1 => array:4 [
      "position" => 2
    ]
    2 => array:4 [
      "position" => 3
    ]
    3 => array:4 [
      "position" => 4
    ]
  ]

However it's actually

 #items: array:4 [
        0 => array:4 [
          "position" => 1
        ]
        1 => array:4 [
          "position" => 1
        ]
        2 => array:4 [
          "position" => 1
        ]
        3 => array:4 [
          "position" => 1
        ]
      ]

Is incrementing inside map not possible or am I doing something wrong here?

1 Answers

The problem here is that you expect $position variable to be passed by reference, which is not the case.

Arrow functions use by-value variable binding. This is roughly equivalent to performing a use($x) for every variable $x used inside the arrow function. A by-value binding means that it is not possible to modify any values from the outer scope. Anonymous functions can be used instead for by-ref bindings. PHP Manual - Arrow Functions

A workaround for you could be like this:

// Either
$posObj = new \stdClass();
$posObj->position = 0;
// or
$posObj = (object)array('position' => 0);

$statement = $medias->map(fn(string $media) => [
                'position' => ++$posObj->position
            ])->values();
Related