Passing Laravel collection by value

44 Views Asked by At

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...
}

1

There are 1 best solutions below

2
miken32 On BEST ANSWER

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...
}