Are PHP objects passed around by reference?

Darrin Deal -

For all this time I though objects were pass around by reference by default in PHP. I was wrong! By looking in the PHP docs I was able to prove I was wrong. In this post I will show the difference between passing variables by reference and how objects are passed around. After reading this post you might see your code differently.

What do I mean by passing by reference?

When you pass a variable as an argument in one of your methods a copy of that variable is created. For example, consider the following function.

<?php

// 1
function add($a, $b){
	$a += $b;
}

$a = 1;
$b = 2;

// 2
echo $a . '\n';

// 3
add($a, $b);

// 4
echo $a;
  1. We have a function that takes two arguments.  Argument 2 is added to argument 1 and argument 1 is returned;
  2. We verify the variable `$a` is equal to 1
  3. The add function is ran.
  4. We verify the variable `$a` is still equal to 1.

The result is:

1
1

This is expected. The $a variable is not affected by us calling the function. The variable is cloned in the scope of the function. Now, by adding an ampersand in front of the $a variable in the function definition we can change the out come. 

<?php

function add(&$a, $b){
	$a += $b;
}

And the result:

1
3

Awesome! This can be useful. You might have already utilized this programing tactic with out knowing. The preg_match() function uses this in it's match function. So then what happens if we pass an object to a function?

How are objects passed then?

Lets start by changing our add function to accept as DTO to represent our object.

function add($dto){
	$dto->result = $dto->a + $dto->b;
}

For this to work we need our DTO object.

class AdditionDTO
{
	public $a;
	
	public $b;
	
	public $result = 0;
}

Now we can look at how to use these items to demonstrate how objects are passed.

// 1
$dto = new AdditionDTO;

// 2
$dto->a = 1;
$dto->b = 2;

// 3
echo $dto->result . "\n";

//4
add($dto);

// 5
echo $dto->result;
  1. Create an instance of our AdditionDTO
  2. Set the a and b properties 
  3. In our definition we set the result to 0 so  to show that we echo out the result.
  4. Perform our add operation by passing in the dto instance
  5. We now echo out our result property after the add operation

The result is:

0
3

It amazing, but why? Why can we pass objects and manipulate them in a local scope and access the manipulation in the global scope? The answer comes down to how data types are stored in variables. When data types list strings, numbers, arrays, etc are stored in memory as that data type. Then when you pass those around clones of that data are created. This is not the same for objects.

When an object is saved to a variable the object is created but not saved to the variable as an object but rather an identifier that points to the object. Then when the variable that holds the object id is accessed regardless of where or how it is accessed it will be the same object. The once exception to this is an object can be cloned. In that case the object is duplicated and the two objects can be independently modified. How cool is that!  

Where to Go From Here?

Take a look at your code. Where can you see this being used? You can also look at open source tools and see this being used there.

You just read the first post on The Art of Laravel. It would mean the world to me if you shared this with your web development friends and follow me on X. Thank you for reading.