Что такое ссылки php
Перейти к содержимому

Что такое ссылки php

  • автор:

Что такое ссылки php

Unlike in C, PHP references are not treated as pre-dereferenced pointers, but as complete aliases.

The data that they are aliasing («referencing») will not become available for garbage collection until all references to it have been removed.

«Regular» variables are themselves considered references, and are not treated differently from variables assigned using =& for the purposes of garbage collection.

The following examples are provided for clarification.

1) When treated as a variable containing a value, references behave as expected. However, they are in fact objects that *reference* the original data.

var = «foo» ;
$ref1 =& $var ; // new object that references $var
$ref2 =& $ref1 ; // references $var directly, not $ref1.

echo $ref1 ; // >Notice: Undefined variable: ref1
echo $ref2 ; // >foo
echo $var ; // >foo
?>

2) When accessed via reference, the original data will not be removed until *all* references to it have been removed. This includes both references and «regular» variables assigned without the & operator, and there are no distinctions made between the two for the purpose of garbage collection.

echo $var ; // >Notice: Undefined variable: var
echo $ref ; // >foo
?>

3) To remove the original data without removing all references to it, simply set it to null.

echo $var ; // Value is NULL, so nothing prints
echo $ref ; // Value is NULL, so nothing prints
?>

4) Placing data in an array also counts as adding one more reference to it, for the purposes of garbage collection.

Что такое ссылки php

Ссылки в PHP позволяют ссылаться на область памяти, где расположено значение переменной или параметра. Для создания ссылки перед переменной указывается символ амперсанда — & . Но перед рассмотрением ссылок сначала рассмотрим простой пример копирования переменных:

"; // tom = Tom echo "sam = $sam"; // sam = Sam ?>

Здесь переменной $sam присваивается значение переменной $tom («Tom»). Затем той же переменной $sam присваивается новое значение — «Sam». Результат программы ожидаем — обе переменные имеют различные значения:

tom = Tom sam = Sam

Теперь при копировании значения переменных передадим ссылку:

"; // tom = Sam echo "sam = $sam"; // sam = Sam ?>

Здесь нас интересует выражение

В данном случае переменной $sam передается не копия значения переменной $tom , как в предыдущем случае, а ссылка на область в памяти, которую занимает переменная $tom . То есть после выполнения инструкции

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

tom = Sam sam = Sam

Присвоить ссылку на переменную можно двумя способами:

$sam = &$tom; // или так $sam = & $tom;

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

В примере в прошлых темах мы передавали параметры по значению . Но в PHP есть и другая форма передачи параметров — по ссылке . Рассмотрим два этих способа передачи параметров и сравним. Стандартная передача параметра по значению:

 $number = 5; square($number); echo "
number = $number"; ?>
a = 25 number = 5

В данном случае внутри функции square() значение параметра $a возводится в квадрат. То есть значение параметра внутри функции изменяется. Однако после вызова функции square() значение переменной $number , которое передается параметру $a, не изменится. Это и есть передача по значению, она никак не затрагивает переменную $number .

Теперь рассмотрим передачу параметра по ссылке:

 $number = 5; square($number); echo "
number = $number"; ?>
a = 25 number = 25

При передаче по ссылке перед параметром ставится знак амперсанда: function square(&$a) . Теперь интерпретатор будет передавать не значение переменной, а ссылку на эту переменную в памяти. То есть теперь и переменная $number и параметр $a будут указывать на одну и ту же область в памяти. В итоге, значение переменной $number после передачи параметру &$a также будет изменено.

Возвращение ссылки из функции

Функция также может возвращать ссылку. В этом случае при определении и вызове функции перед ее именем ставится знак амперсанда:

 $userName = "admin"; $checkedName = &checkName($userName); echo "
userName: $userName"; echo "
checkedName: $checkedName"; ?>

В данном случае функция checkName() получает параметр по ссылке и возвращает ссылку — фактически ссылку, которая передается в функции. Для этого перед определением функции указан символ амперсанда:

Для имитации работы функция проверяет имя пользователя и изменяет его на некоторое стандартное, если оно равно «admin».

При вызове функции перед ее именем указывается символ амерсанда:

После выполнения функции переменная $checkedName фактически будет содержать ссылку на переменную $userName .

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

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

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

Для начала, ссылки PHP позволяют создать две переменные указывающие на одно и тоже значение. Таким образом, когда выполняется следующее:

то $a указывает на то же значение что и $b .

Замечание:

$a и $b здесь абсолютно эквивалентны, но это не означает, что $a указывает на $b или наоборот. Это означает, что $a и $b указывают на одно и тоже значение.

Замечание:

При присвоении, передаче или возврате неинициализированной переменной по ссылке, происходит ее создание.

Пример #1 Использование ссылок с неинициализированными переменными

function foo (& $var )

foo ( $a ); // $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)
?>

Такой же синтаксис можно использовать и в функциях, возвращая ссылки, а так же в операторе new (начиная с PHP 4.0.4 и до PHP 5.0.0):

Начиная с PHP 5, new автоматически возвращает объекты по ссылке, поэтому использовать =& в этом случае нерекомендуется и вызывает сообщение E_DEPRECATED в PHP 5.3 и последующих версиях, а также сообщение E_STRICT в более ранних версиях. (Технически разница в том, что в PHP 5 переменные объектов, так же как и ресурсы, являются просто указателями на реальные данные объекта, поэтому ссылки на объекты не те же самые «ссылки», о которых говорилось ранее (псевдонимы). Подробнее в Объекты и ссылки.)

Внимание

Если переменной, объявленной внутри функции как global, будет присвоена ссылка, она будет видна только в функции. Чтобы избежать этого, используйте массив $GLOBALS .

Пример #2 Присвоение ссылок глобальным переменным внутри функции

function global_references ( $use_globals )
global $var1 , $var2 ;
if (! $use_globals ) $var2 =& $var1 ; // только локально
> else $GLOBALS [ «var2» ] =& $var1 ; // глобально
>
>

global_references ( false );
echo «значение var2: ‘ $var2 ‘\n» ; // значение var2: »
global_references ( true );
echo «значение var2: ‘ $var2 ‘\n» ; // значение var2: ‘Example variable’
?>

Думайте о global $var; как о сокращении от $var =& $GLOBALS[‘var’];. Таким образом, присвоение $var другой ссылки влияет лишь на локальную переменную.

Замечание:

При использовании переменной-ссылки в foreach, изменяется содержание, на которое она ссылается.

Пример #3 Ссылки и foreach

$ref = 0 ;
$row =& $ref ;
foreach (array( 1 , 2 , 3 ) as $row ) // do something
>
echo $ref ; // 3 — последнее значение, используемое в цикле
?>

Хотя, стого говоря, в выражениях, создаваемых с помощью конструкции array(), нет присвоения, но тем не менее можно указать префикс & для элементов массива. Пример:

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

/* Присвоение скалярных переменных */
$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 изменилось, хотя было присвоено не по ссылке! */
?>

Иными словами, поведение отдельных элементов массива не зависит от типа присвоения этого массива.

Pass By Reference

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

Этот код присвоит $a значение 6. Это происходит, потому что в функции foo переменная $var ссылается на то же содержимое, что и переменная $a . См. также детальное объяснение передачи по ссылке.

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

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

Ссылки в PHP

Ссылки в PHP — это средство доступа к содержимому одной переменной под разными именами. Они не похожи на указатели C и не являются псевдонимами таблицы символов. В PHP имя переменной и её содержимое — это разные вещи, поэтому одно содержимое может иметь разные имена. Ближайшая аналогия — имена файлов Unix и файлы — имена переменных являются элементами каталогов, а содержимое переменных это сами файлы. Ссылки в PHP — аналог жёстких ссылок (hardlinks) в файловых

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

Ссылки в PHP дают возможность двум переменным ссылаться на одно содержимое. Например:

означает, что $a указывает на то же содержание, что и $b.

Замечание: $a и $b здесь абсолютно эквивалентны, но это не означает, что $a указывает на $b или наоборот. Это означает, что $a и $b указывают на одно место.

Замечание: При копировании массива ссылок, они не разыменовываются. Это также касается массивов, передаваемых функциям по значению.

Такой же синтаксис можно использовать и в функциях, возвращая ссылки, а так же в операторе new (начиная с PHP 4.0.4):

$bar =& new fooclass(); $foo =& find_var($bar);

Замечание: Если опустить &, это приведёт к копированию объекта. Если вы используете $this в классе, операция проводится над текущим экземпляром этого класса. Присвоение без & приведёт к копированию экземпляра, и $this будет работать с копией, что не всегда желательно. Обычно, вам нужно иметь один экземпляр, из соображений производительности и использования памяти.

Операция @, которая скрывает сообщения об ошибках, например в конструкторе @new, не может быть использована совместно с операцией & (&new). Это ограничение интерпретатора Zend.

Внимание: Если переменной, объявленной внутри функции как global, будет присвоена ссылка, она будет видна только в функции. Чтобы избежать это, воспользуйтесь массивом $GLOBALS.

Пример. Присвоение ссылок глобальным переменным внутри функции
$var1 = "Example variable"; $var2 = ""; function global_references($use_globals) < global $var1, $var2; if (!$use_globals) < $var2 =& $var1; // только локально >else < $GLOBALS["var2"] =& $var1; // глобально >> global_references(false); echo "значение var2: '$var2'\n"; // значение var2: '' global_references(true); echo "значение var2: '$var2'\n"; // значение var2: 'Example variable'

Думайте о global $var; как о сокращении от $var =& $GLOBALS[‘var’];. Таким образом, присвоение $var другой ссылки влияет лишь на локальную переменную.

Замечание: При использовании переменной-ссылки в foreach, изменяется содержание, на которое она ссылается.

Пример. Ссылки и foreach
$ref = 0; $row =& $ref; foreach (array(1, 2, 3) as $row) < // do something >echo $ref; // 3 - последнее значение, используемое в цикле

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

Пример. Ссылки и сложные массивы
$top = array( 'A' => array(), 'B' => array( 'B_b' => array(), ), ); $top['A']['parent'] = &$top; $top['B']['parent'] = &$top; $top['B']['B_b']['data'] = 'test'; print_r($top['A']['parent']['B']['B_b']); // array()

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

function foo(&$var) < $var++; >$a=5; foo($a);

Этот код присвоит $a значение 6. Это происходит, потому что в функции foo переменная $var ссылается на то же содержимое, что и переменная $a. См. также детальное объяснение передачи по ссылке.

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

Чем ссылки не являются

ссылки не являются указателями. Это означает, что следующая конструкция не будет делать то, что вы ожидаете:

function foo(&$var) < $var =& $GLOBALS["baz"]; >foo($bar);

Переменная $var в фукнции foo будет связана с $bar в вызывателе, но затем она будет перепривязана к $GLOBALS[«baz»]. Нет способа связать $bar в области видимости вызывателя с чем-либо ещё путём использования механизма ссылок, поскольку $bar не доступна в функции foo (доступно лишь её значение через $var). Вы можете воспользоваться возвращением ссылок из функции для привязки внешней перменной к другому значению.

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

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

function foo(&$var) < $var++; >$a=5; foo($a); // $a здесь равно 6

Заметьте, что в вызове функции отсутствует знак ссылки — он есть только в определении функции. Этого достаточно для корректной передачи аргументов по ссылке.

  • Переменные, например foo($a)
  • Оператор new, например foo(new foobar())
  • Ссылки, возвращаемые функцией, например:

function &bar() < $a = 5; return $a; >foo(bar());

Любое другое выражение не должно передаваться по ссылке, так как результат не определён. Например, следующая передача по ссылке является неправильной:

function bar() // Операция & отсутствует < $a = 5; return $a; >foo(bar()); foo($a = 5); // Выражение, а не переменная foo(5); // Константа, а не переменная

Эти требования для PHP 4.0.4 и позже.

Возвращение по ссылке

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

function &find_var($param) < /* . код . */ return $found_var; >$foo =& find_var($bar); $foo->x = 2;

В этом примере устанавливается свойство объекта, возвращённого функцией find_var, а не его копии, как было бы без использования ссылок.

Замечание: В отличие от передачи параметров по ссылке, & здесь нужно использовать в обоих местах — для указания на то, что вы возвращаете ссылку, а не копию, как обычно, и для указания того, что происходит связывание по ссылке, а не обычное присвоение.

Сброс переменных-ссылок

При сбросе ссылки, просто разрывается связь имени и содержимого переменной. Это не означает, что содержимое переменной будет разрушено. Например:

$a = 1; $b =& $a; unset($a);

Этот код не сбросит $b, а только $a.

Опять же, можно провести аналогию с вызовом unlink (в Unix).

Неявное использование механизма ссылок

Многие синтаксические конструкции PHP реализованы через механизм ссылок, поэтому всё сказанное выше о ссылочном связывании применимо также и к этим конструкциям. Некоторые конструкции, вроде передающих и возвращающих по ссылке, рассмотрены ранее. Другие конструкции, использующие ссылки:

Ссылки global

Если вы объявляете переменную как global $var, вы фактически создаёте ссылку на глобальную переменную. Это означает то же самое, что:

Это значит, например, что сброс (unset) $var не приведёт к сбросу глобальной переменной.

$this

В методах объекта, $this всегда является ссылкой на вызывающий объект.

Добавить комментарий

Ваш адрес email не будет опубликован. Обязательные поля помечены *