Assigning Variables by Reference

Hello,

I was having a read through the PHP manual and I came to the part about assigning variables by reference, which are basically two different variable names pointing to the same content. So if you edit, one you edit both.

The example from php.net

<?php
$foo = 'Bob';              // Assign the value 'Bob' to $foo
$bar = &$foo;              // Reference $foo via $bar.
$bar = "My name is $bar";  // Alter $bar...
echo $bar;
echo $foo;                 // $foo is altered too.
?>

My question is, what problem does this solve?

Thanks!

It’s useful for creating functions which can modify one or more variables and return yet something else.

I don’t use these much, but they can save on memory


$a = 50;

function test(&$a) {
  echo $a;
}

// You dont have to pass a paremeter
test();

Thanks for the replies!

I take it that assigning variables by reference is mainly useful going from a global scope to a local scope?

@JREAM. When I tried your snippet, PHP threw a warning for a missing argument and a notice for an undefined variable ‘a’ at your echo statement. I’m using PHP 5.3.0 and I know that some of the behavior for passing things by reference was changed, perhaps that’s why it’s throwing a warning?

Expanding on JREAM’s example

$a = 50;

function test(&$var) 
{
	if($var == 50)
	{
		$var = $var * 2;
		
		return '$a should now be 100.';
	}  
	
	return '$a should retain original value.';
}

$result = test($a);

echo $result; // Outputs $a should now be 100.

echo $a; // Outputs 100
         // Without the '&' in the function signature it outputs 50.

I can see the advantage of altering a variable while returning something else, however, wouldn’t this add some ambiguity into the code?

Are there any other use cases for passing variables by reference?

Well usually a variable is passed by reference when you want to be able to alter it. You might want to use it for recursive functions, where you return true / false but you’re still able to alter the contents of the variable you work with.
There are many native php functions that operate in such way.
I really can’t think of any other use otherwise, as I can’t really see any other :slight_smile:

It’s also useful for applications with multiple threads where all the threads need to be able modify one and the same variable somewhere.
Since PHP doesn’t do multithreading my comment is kinda moot, but I thought I’d throw it in here for the sake of completeness :slight_smile:

The data here would typically come from a database with linear storage of data rows.

<?php
/*

     1
 2      3
4 5    6 7

*/

$tree = array(
	1 => array(
		'name' => 'One',
		'parent' => null,
		'children' => array()
	),
	2 => array('name' => 'Twp','parent' => 1, 'children' => array()),
	3 => array('name' => 'Three','parent' => 1, 'children' => array()),
	4 => array('name' => 'Four','parent' => 2, 'children' => array()),
	5 => array('name' => 'Five','parent' => 2, 'children' => array()),
	6 => array('name' => 'Six','parent' => 3, 'children' => array()),
	7 => array('name' => 'Seven','parent' => 3, 'children' => array()),
);

foreach($tree as $id => $data)
{
	if($data['parent'])
	{
		$tree[$data['parent']]['children'][$id] =& $tree[$id];
	}
}

print_r($tree);
echo PHP_EOL;

?>

While the data can be worked with as a multi-dimensional array as this print_r output shows, it’s still stored in memory as a single dimensional array. This means linear operations, such as counting the total number of nodes, can still be performed easily. Also, rather than looping through the results multiple times to collect children for each node, the array is looped through once to assign references.

Array
(
	[1] => Array
		(
			[name] => One
			[parent] => 
			[children] => Array
				(
					[2] => Array
						(
							[name] => Twp
							[parent] => 1
							[children] => Array
								(
									[4] => Array
										(
											[name] => Four
											[parent] => 2
											[children] => Array()
										)
									[5] => Array
										(
											[name] => Five
											[parent] => 2
											[children] => Array()
										)
								)
						)
					[3] => Array
						(
							[name] => Three
							[parent] => 1
							[children] => Array
								(
									[6] => Array
										(
											[name] => Six
											[parent] => 3
											[children] => Array()
										)
									[7] => Array
										(
											[name] => Seven
											[parent] => 3
											[children] => Array()
										)
								)
						)
				)
		)
	[2] => Array
		(
			[name] => Twp
			[parent] => 1
			[children] => Array
				(
					[4] => Array
						(
							[name] => Four
							[parent] => 2
							[children] => Array()
						)
					[5] => Array
						(
							[name] => Five
							[parent] => 2
							[children] => Array()
						)
				)
		)
	[3] => Array
		(
			[name] => Three
			[parent] => 1
			[children] => Array
				(
					[6] => Array
						(
							[name] => Six
							[parent] => 3
							[children] => Array()
						)
					[7] => Array
						(
							[name] => Seven
							[parent] => 3
							[children] => Array()
						)
				)
		)
	[4] => Array
		(
			[name] => Four
			[parent] => 2
			[children] => Array()
		)
	[5] => Array
		(
			[name] => Five
			[parent] => 2
			[children] => Array()
		)
	[6] => Array
		(
			[name] => Six
			[parent] => 3
			[children] => Array()
		)
	[7] => Array
		(
			[name] => Seven
			[parent] => 3
			[children] => Array()
		)
)

Thanks joebert!

I was struggling to see a use for assign by reference but your example clearly show how useful they can be. You have been a tremendous help.

Be very careful when doing something like this. It’s possible to bring your site down with SEGFAULT errors of you accidentally allow a node to reference itself as a parent.