Be part of JetBrains PHPverse 2026 on June 9 – a free online event bringing PHP devs worldwide together.

Burdyle's avatar

Original array gets modified in function without the '&' ?

Hello! I'm trying to understand why the modifications I make in the argument array also modifies the original array. I thought that when you pass a argument to a function, you pass a "copy" unless you use the '&'?

Here's my code :

$users = Users::all()

function addThreeYearsToUsers($users) {
   foreach ($users as $user) {
      $user->age = $user->age + 3;
   }			
}
addThreeYearsToUsers($users) 
dd($users)

After the function is called, every users have + 3 years. Is it normal? I didn't use the '&', nor used $user->save()...

I'm confused! Thank you!

0 likes
7 replies
LaryAI's avatar
Level 58

Hello!

The behavior you're observing is due to the fact that objects in PHP are passed by reference by default. This means that when you pass an object to a function, you're actually passing a reference to the original object, not a copy of it. Therefore, any changes you make to the object's properties within the function will affect the original object.

In your code, $users is a collection of user objects. When you pass $users to the addThreeYearsToUsers function and iterate over it, you're modifying the properties of the objects within that collection. Since objects are reference types, the original user objects in the $users collection are updated.

Here's a modified version of your code that clarifies this concept:

$users = Users::all();

function addThreeYearsToUsers($users) {
   foreach ($users as $user) {
      $user->age += 3; // This modifies the original user object's age property
   }			
}

addThreeYearsToUsers($users);
dd($users);

If you want to avoid modifying the original objects, you would need to clone each object before making changes to it. Here's how you could do that:

$users = Users::all();

function addThreeYearsToUsers($users) {
   $modifiedUsers = [];
   foreach ($users as $user) {
      $clonedUser = clone $user; // Create a shallow copy of the user object
      $clonedUser->age += 3; // Modify the cloned object
      $modifiedUsers[] = $clonedUser; // Add the cloned object to the new array
   }
   return $modifiedUsers; // Return the new array with modified cloned objects
}

$usersWithAddedYears = addThreeYearsToUsers($users);
dd($usersWithAddedYears); // This will show the modified ages
dd($users); // This will show the original ages, unchanged

In this modified version, the original $users array remains unchanged, and a new array $usersWithAddedYears contains the cloned and modified user objects.

Burdyle's avatar

So if I understand correctly, primitive objects like strings or floats are passed as a "copy", but objects though are passed by reference by default?

gych's avatar

What do you mean extactly?

You're calling the function addThreeYearsToUsers for the $users collection. Which will add +3 years of age to all the users in that collection.

After that you dump and die the $users collection which will show you all the users that you've just updated. In your DB the users will still have their original age without the +3 years, since from what I see you never update this data in the database.

Burdyle's avatar

@gych I didn't know object were passed by reference. So for example :

$numbers = [1, 2];
addNumberThreeToArray($numbers) 
dd($numbers)

function addNumberThreeToArray($numbers) {
	$numbers[] = 3;
}

In my head, the dump should be "[1, 2]" and that's what I'm getting because $numbers is NOT passed by reference. But in my previous example, it didn't make any sense to me until I realized $users was not an array, but rather an object.

Does that make any sense of I'm not understanding correctly?

gych's avatar

@Burdyle Yes it makes sense but $users is not just an object its a collection

You can test this now with these numbers by making $numbers a collection instead of an array

$numbers = collect([1, 2]);

If you want to use the $users as array instead of a collection you can convert a collection to an array by using toArray()

$users->toArray()

You can also check these docs for a bit more info on collections: https://laravel.com/docs/10.x/collections

gych's avatar

@Burdyle No problem :) don't forget to close your post by selecting the best answer. If you have any more questions don't hesitate to reach out.

Please or to participate in this conversation.