Со ссылками выполняют три базовые операции: присваивание по ссылке, передача по ссылке и возврат по ссылке. Глава знакомит читателя с этими операциями и даёт ссылки на дополнительные материалы для изучения.
Первое, что делают ссылки в PHP, — разрешают создавать две переменные, которые ссылаются на одно и то же значение. Когда выражение записывают вот так:
<?php
$a =& $b;
?>
Замечание:
Переменные $a и $b, которые приводит пример, — эквивалентны. Переменная $a не указывает на переменную $b или наоборот. Переменные $a и $b указывают на одно и то же значение.
Замечание:
PHP создаст переменную, если неинициализированную переменную присвоили, передали или вернули по ссылке.
Пример #1 Пример присваивания ссылок с неопределёнными переменными
<?php
function foo(&$var) {}
foo($a); // PHP создал переменную $a и присвоил ей значение null
$b = array();
foo($b['b']);
var_dump(array_key_exists('b', $b)); // bool(true)
$c = new stdClass();
foo($c->d);
var_dump(property_exists($c, 'd')); // bool(true)
?>
Таким же синтаксисом разрешается пользоваться при вызове функций, из которых возвращаются ссылки на значения:
<?php
$foo =& find_var($bar);
?>
Обращение через такой синтаксис к функции, которая не возвращает значение по ссылке, выдаст ошибку, равно как и обращение через такой синтаксис к результату, который возвращает оператор new. Объекты хотя и передаются как указатели, это не то же, что ссылки, как объясняет раздел «Объекты и ссылки».
Ссылка будет видна только внутри функции, если присвоить ссылку переменной,
которую объявили внутри функции через ключевое слово global
.
Чтобы избежать этого и сделать ссылку видимой в глобальном контексте,
ссылку присваивают переменной суперглобального массива $GLOBALS.
Пример #2 Пример присваивания ссылок переменным, которые объявили внутри функции через ключевое слово global
<?php
$var1 = "Пример переменной";
$var2 = "";
function global_references($use_globals)
{
global $var1, $var2;
if (!$use_globals) {
$var2 =& $var1; // Ссылка $var1 видна только внутри функции
} else {
$GLOBALS["var2"] =& $var1; // Ссылка $var1 видна также в глобальном контексте
}
}
global_references(false);
echo "Переменной \$var2 установили значение '$var2'\n"; // Переменной $var установили значение ''
global_references(true);
echo "Переменной \$var2 установили значение '$var2'\n"; // Переменной $var установили значение 'Пример переменной'
?>
global $var;
думают как о сокращённой записи
выражения $var =& $GLOBALS['var'];
, в котором переменной
присваивается ссылка. Поэтому присваивание переменной $var
другой ссылки
изменяет ссылку только локальной переменной.
Замечание:
Когда в инструкции
foreach
значение присваивается переменной, которая хранит ссылку, значение ссылки тоже изменяется.Пример #3 Пример ссылок в конструкции foreach
<?php
$ref = 0;
$row =& $ref;
foreach (array(1, 2, 3) as $row) {
// Сделать что-нибудь
}
echo $ref; // 3 — значение последнего элемента массива, который перебирался в цикле
?>
Выражения с языковой конструкцией array()
умеют вести себя как присваивание по ссылке, хотя и не через строгий синтаксис присваивания по ссылке,
а путём добавления префикса &
к добавляемому элементу массива. Приведём пример:
<?php
$a = 1;
$b = array(2, 3);
$arr = array(&$a, &$b[0], &$b[1]);
$arr[0]++;
$arr[1]++;
$arr[2]++;
/* $a == 2, $b == array(3, 4); */
?>
Однако обратите внимание, что ссылки внутри массивов несут опасность. Стандартные (не по ссылке) присваивания со ссылкой в правой части не превращают левую часть в ссылку, но ссылки внутри массивов сохраняются при стандартных присваиваниях. Это также относится к вызовам функций, в которых массив передаётся по значению. Приведём пример:
<?php
/* Присваивание скалярных переменных */
$a = 1;
$b =& $a;
$c = $b;
$c = 7; // Переменная $c — не ссылка; переменные $a и $b не изменились
/* Присваивание переменных, которые содержат массив */
$arr = array(1);
$a =& $arr[0]; // Переменные $a и $arr[0] входят в один набор ссылок
$arr2 = $arr; // Присваивание по значению, а не по ссылке!
$arr2[0]++;
/* $a == 2, $arr == array(2) */
/* Содержимое переменной $arr изменяется, даже если это не ссылка! */
?>
Второе, что умеют делать ссылки, — передавать переменные по ссылке. Для этого создают две переменные, которые ссылаются на одно и то же содержимое: одну — в функции, а другую — в области видимости вызова. Следующий пример:
<?php
function foo(&$var)
{
$var++;
}
$a = 5;
foo($a);
?>
Третье, что умеют делать ссылки, — возвращать по ссылке.