Что делают ссылки

Со ссылками выполняют три базовые операции: присваивание по ссылке, передача по ссылке и возврат по ссылке. Глава знакомит читателя с этими операциями и даёт ссылки на дополнительные материалы для изучения.

Присваивание по ссылке

Первое, что делают ссылки в PHP, — разрешают создавать две переменные, которые ссылаются на одно и то же значение. Когда выражение записывают вот так:

<?php

$a
=& $b;

?>
переменные $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);

?>
изменит значение, на которое указывает переменная $a, на 6. Причина состоит в том, что в функции foo переменная $var ссылается на то же содержимое, что и переменная $a. Дополнительную информацию об этом даёт раздел о передаче по ссылке.

Возврат ссылок

Третье, что умеют делать ссылки, — возвращать по ссылке.