Today I encountered a behaviour which I did not expect in PHP 8.2. See following code:
Code
function foo(&$undefined) {
if (is_null($undefined)) {
return sprintf('value: "%s"', $undefined);
}
}
print(foo($undefined)) . "n";
var_dump($undefined);
Result
value: ""
NULL
As you can see, the variable $bar
is undefined. While I expected a fatal error, I can pass it by reference which no problems. It seems that &$undefined
renders to null
.
Is that due to historic reasons and would one usually expect that from other languages as well?
4
The reason this doesn’t cause an error is because the call to the function with a variable creates the variable. There are a number of common situations where we can usefully call a function that takes a reference variable, but it doesn’t need an initial value. Either the function will assign the variable, or it just saves the reference to be read later.
Since PHP doesn’t have a way of declaring a variable without initializing it (except for class properties), and the value isn’t needed, it would not be appropriate to complain that the variable hasn’t been initialized when the value isn’t needed.
There are examples of both types in the mysqli
extension library (and also PDO
). Both mysqli_stmt::bind_result()
and mysqli_stmt::bind_param()
save the variable references for later.
mysqli_stmt::bind_result()
assigns the saved references when you call mysqli_stmt::fetch()
. It assigns columns of the query result to the variables you specified. Example code:
$stmt = $conn->prepare("SELECT col1, col2 FROM tablename");
$stmt->bind_result($col1, $col2);
$stmt->execute();
while ($stmt->fetch()) {
echo "Column 1: $col1 Column2: $col2 <br>";
}
Conversely mysqli_stmt::bind_param()
saves the references to read them later. You bind to variables that you plan on assigning later, e.g. in a loop.
$stmt = $conn->prepare("INSERT INTO tablename (col1, col2) VALUES (?, ?)");
// bind to references to these nonexistent variables
$stmt->bind_param("ss", $var1, $var2);
foreach ($data_array as [$var1, $var2]) { // assign the variables
$stmt->execute();
}
Finally, another common function uses a reference parameter as an out parameter: preg_match()
. The $match
parameter is a variable supplied by the caller that will be assigned the array containing the part of the string that matched the regular expressions and the capture groups. There’s no need to initialize this before calling the function, since any previous value will be overwritten by the function.
3