Search code examples
laravelcollectionscall-by-value

Passing Laravel collection by value


I'm trying passing an Laravel Eloquent collection into a function, inside the function I'm doing some collection manipulation. If I do something like map method on the collection, it will also alter the underlying models for the outer collection variable.

How can I passing collection by value into a function? I tried clone and ->collect() method, but seems not work.

Thanks.

$users = User::where('type', 1)->get();

$this->doSomething($users);
// or
$this->doSomething(clone $users);
// or
$this->doSomething($users->collect());

foreach($users as $user)
{
    $user->location; // has been modified in 'doSomething' function.

}

private function doSomething(Collection $users)
{
    $mapUsers = $users->map(function ($user) {
            $user->location = 'some value';
            return $user;
        });

    // using $mapUsers...
}


Solution

  • Was going to leave this as a comment but it was getting too verbose. When you clone the collection, the references inside remain the same.

    You have two options: if you need to work with actual User objects, do this:

    $users = User::where('type', 1)->get();
    
    $this->doSomething($users);
    
    foreach($users as $user) {
        echo $user->location;
    }
    
    private function doSomething(Collection $users)
    {
        $mapUsers = $users->map(function (User $user) {
            $u = clone $user;
            $u->location = 'some value';
            return $u;
        });
    
        // using $mapUsers...
    }
    

    Or less complicated, if you just need the values, would be to pass an array. The toArray() method is recursive, so it turns the inside objects into arrays as well:

    $users = User::where('type', 1)->get();
    
    $this->doSomething($users->toArray());
    
    foreach($users as $user) {
        echo $user->location;
    }
    
    private function doSomething(array $users)
    {
        $mapUsers = collect($users)->map(function (array $user) {
            $user['location'] = 'some value';
            return $user;
        });
    
        // using $mapUsers...
    }