John Mwaniki /   14 Apr 2023

[Solved] Notice: Only variables should be passed by reference

When working with certain functions in PHP, you are likely to encounter the notice below at some point.

Notice: Only variables should be passed by reference in /path/to/file.php on line xx

Some of the commonly known built-in functions that result in this notice include end(), bind_param(), and array_pop().

If you are stuck on fixing this, then this article is for you. In this article, we will explore what this notice means and how to resolve it.

Understanding the Notice

The notice "Only variables should be passed by reference" is a PHP notice message that is triggered when a function is called with a parameter that is not a variable.

When a function is called with a reference parameter, the function expects a variable to be passed. If a non-variable is passed instead, the notice is triggered.

Notice with the end() functions

The end() function takes in an array as a parameter and returns the value of the last element in the array or false for an empty array.

It works by moving the internal pointer of an array to its last element.

Syntax

end(array)

Example

<?php
$animals = array('Elephant', 'Lion', 'Crocodile', 'Leopard');
echo end($animals);
?>

Output:
Leopard

You can also form the array to pass into the end() function using the explode() function. The explode() function breaks a string into an array.

Example

<?php
$str = 'I love programming in PHP';
print_r(explode(' ', $str));
?>

Output:
Array (
  [0] => I
  [1] => love
  [2] => programming
  [3] => in
  [4] => PHP
)

In the explode() function, the first parameter is referred to as the "separator" and it specifies where to break the string while the second is the string to split into an array. In the above example, we have used the space (' ') as the separator, breaking the string down into array elements in all the instances of space.

You can also form an array in PHP from a JSON object using the json_decode() function as shown below.

<?php
$person = '{"name":"John", "age":"30", "gender":"Male", "country":"Kenya"}';
$array = json_decode($person,true);
print_r($array);
?>

Output:
Array (   [name] => John
  [age] => 30
  [gender] => Male
  [country] => Kenya
)

If you pass the explode() function directly into the end() function as in the code below;

<?php
$str = 'I love programming in PHP';
echo end(explode(' ', $str));
?>

Or pass the json_decode() function into the end() function as below;

<?php
$person = '{"name":"John", "age":"30", "gender":"Male", "country":"Kenya"}';
echo end(json_decode($person,true));
?>

You will get the notice below:

Notice: Only variables should be passed by reference in /path/to/file.php on line xx

This is because as the notice suggests, only an actual variable should be passed to the end() function but we have instead passed a function in the two examples.

The argument for end() function is supposed to be passed by reference since this function modifies the array by moving its internal pointer to the last element. If you are not passing a variable in, there is nothing for a reference to point to (the results of explode(' ', $str) or json_decode($person,true) cannot be turned into a reference).

The Solution

Split the code and assign the result of the explode() function to a variable. Then pass that variable to end() function.

<?php
$str = 'I love programming in PHP';
$myarray = explode(' ', $str);
echo end($myarray);
?>

Output:
PHP

In the case of json_decode() function, first convert the JSON object into a PHP array and assign its result to a variable. Then pass that variable to end() function.

<?php
$person = '{"name":"John", "age":"30", "gender":"Male", "country":"Kenya"}';
$array = json_decode($person,true);
echo end($array);
?>

Output:
Kenya

Some developers use the @ prefix to the end() function to suppress the notice.

<?php
$str = 'I love programming in PHP';
echo @end((explode(' ', $str)));
/*
Or as below in the case of json_decode
*/
$person = '{"name":"John", "age":"30", "gender":"Male", "country":"Kenya"}';
echo @end(json_decode($person,true));
?>

It works fine but suppressing notices, warnings, and errors is not encouraged.

Another alternative method is to substitute end and explode functions with substr() and strrchr() functions as in the example below.

<?php
$str = 'I love programming in PHP';
echo substr( strrchr($str, ' '), 1);
?>

If you are using the explode() and end() functions to get the extension of a file from its file name by getting the part after the last dot(.), you can substitute that with the pathinfo() function.

Example 1

<?php
$file_name = "Sample-document.pdf";
echo pathinfo($file_name, PATHINFO_EXTENSION);
?>

Output:
pdf

Notice with the array_pop() functions

This notice is also common when using the array_pop() function.

The array_pop() function takes in an array as the only argument, and deletes the last element of that array. It returns the value of the last element of the array or null if the array is empty.

Example 1

<?php
$fruits = array("Apple", "Avocado", "Melon", "Orange", "Banana");
echo array_pop($fruits);
?>

Output:
Banana

As you can see above, the function returns the value of the last element of the array.

Example 2

<?php
$fruits = array("Apple", "Avocado", "Melon", "Orange", "Banana");
array_pop($fruits);
print_r($fruits);
?>

Output:
Array (
  [0] => Apple
  [1] => Avocado
  [2] => Melon
  [3] => Orange
)

As you can see above, the last element of the array (Banana) has been deleted from the array.

Similarly to the end() function, passing a function to the array_pop() function will result in the "Only variables should be passed by reference" notice.

<?php
$str = 'I love programming in PHP';
array_pop(explode(' ', $str));

//Or
$person = '{"name":"John", "age":"30", "gender":"Male", "country":"Kenya"}';
array_pop(json_decode($person,true));
?>

The Solution

The solution is the same as that of the end() function. Don't pass a function into array_pop() but instead assign the result of that function to a variable. Then pass that variable to the array_pop() function.

<?php
$str = 'I love programming in PHP';
$myarray = explode(' ', $str);
array_pop($myarray);
print_r($myarray);

//Or
$person = '{"name":"John", "age":"30", "gender":"Male", "country":"Kenya"}';
$array = json_decode($person,true);
array_pop($array);
print_r($array);
?>

Notice with the bind_param() functions

You may also experience the same issue when working with MySQLi prepared statements in the bind_param() function.

Example

<?php
include_once("db-connection.php");
$name = "John";
$stmt = $con->prepare("INSERT INTO test(name,created_at) VALUES(?,?)");
$stmt->bind_param("ss", $name, date("Y-m-d"));
$stmt->execute();
?>

The above code will display/log the notice below:

Notice: Only variables should be passed by reference in /path/to/file.php on line 5

The notice is due to the use of the date() function within the bind_param() function.

To fix the notice in the above code, assign the return value of date("Y-m-d") to a variable and use that variable as the bind parameter.

<?php
include_once("db-connection.php");
$name = "John";
$date = date("Y-m-d");
$stmt = $con->prepare("INSERT INTO test(name,created_at) VALUES(?,?)");
$stmt->bind_param("ss", $name, $date);
$stmt->execute();
?>

The bind_param() function takes values by reference. It expects parameters to be variables so you cannot use return values from functions directly.

Besides the first parameter in the bind_param() function, always pass the other parameters as variables and not function return values.

In case you experience the same notice when working with another function besides those discussed here, the first thing should be to ensure that you are passing only variables as parameters to the function.