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

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

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

Первое, что делают ссылки в 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); */
    var_dump($a);
    var_dump($b);

Однако обратите внимание, что ссылки внутри массивов несут опасность. Стандартные (не по ссылке) присваивания со ссылкой в правой части не превращают левую часть в ссылку, но ссылки внутри массивов сохраняются при стандартных присваиваниях. Это также относится к вызовам функций, в которых массив передаётся по значению. Приведём пример:

    <?php

    /* Присваивание скалярных переменных */
    $a = 1;
    $b =& $a;
    $c = $b;
    $c = 7; // Переменная $c — не ссылка; переменные $a и $b не изменились
    print "a = {$a}; b = {$b}; c = {$c}\n\n";

    /* Присваивание переменных, которые содержат массив */
    $arr = array(1);
    $a =& $arr[0]; // Переменные $a и $arr[0] входят в один набор ссылок
    $arr2 = $arr; // Присваивание по значению, а не по ссылке!
    $arr2[0]++;
    /* $a == 2, $arr == array(2) */
    /* Содержимое переменной $arr изменяется, даже если это не ссылка! */
    print "a = {$a}\n";
    var_dump($arr);
    var_dump($arr2);

Другими словами, ссылочное поведение массивов определяется поэлементно; ссылочное поведение отдельных элементов массива не зависит от ссылочного статуса контейнера массива.

### Передача по ссылке

Второе, что умеют делать ссылки, — передавать переменные по ссылке. Для этого создают две переменные, которые ссылаются на одно и то же содержимое: одну — в функции, а другую — в области видимости вызова. Следующий пример:

    <?php
    function foo(&$var)
    {
        $var++;
    }

    $a = 5;
    foo($a);
    print $a;

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

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

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

`↑` and `↓` to navigate • `Enter` to select • `Esc` to close • `/` to open