Главная страница » Что такое ссылки php

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

  • автор:

References в PHP

Сегодня будем разбираться со ссылками (references) в PHP.

Начнем издалека. Под словом “издалека” в данном контексте подразумевается язык программирования C.

Указатели в C

Указатель — это переменная, содержащая адрес другой переменной.

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

На этом рисунке указатель p (ячейка памяти №2) указывает на переменную v (ячейка памяти №12).

В коде это можно изобразить так:

С помощью оператора & мы получаем адрес объекта v и присваиваем его переменной p.

В языке C существует также оператор разыменования (*), если мы его применим к указателю, тогда получим объект на который он указывает, например:

Указатели и аргументы функций в C

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

То есть (смотрим комментарий в коде):

Для того чтобы обнулить переменные a и b с помощью функции sub необходимо передать в нее не копии, а указатели на переменные:

Переходим к PHP

О том, что собой представляют указатели в C мы вкратце поговорили, пришло время переходить к PHP.

Присвоение по значению

В PHP информация о переменных хранится в символьных таблицах:

На рисунке выше имена $a и $b которые находятся в символьной таблице указывают на соответствующие данные в неком контейнере.

Давайте теперь посмотрим что произойдет после выполнения операции присвоения по значению (assign by value):

Как видите, PHP не копирует данные, а лишь увеличивает счетчик ссылок (ref_count), за счет чего имеем экономию памяти. При вызове unset() счетчик уменьшается на 1. Если счетчик ссылок меньше 1, тогда контейнер переменной очищается.

Передача переменных в функцию

Давайте посмотрим, что происходит когда мы пишем следующий код:

1. $a = ‘some text’. Создается символьная таблица, подобно той которую мы уже рисовали:

2. $b = myFunction($a). Создается еще одна символьная таблица, в которой имя $var указывает на те же данные что и $a (время жизни этой таблицы равно времени выполнения функции). Также создается стек вызова функции, который тоже ссылается на данные:

3. $var = ‘changed text’. Теперь имя $var во временной таблице указывает на другие данные:

4. После выполнения операторов return $var; и $b = myFunction($a); получим следующую картину:

5. И напоследок, завершается выполнение функции, а соответственно очищается временная таблица символов и стек функции:

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

Присвоение по ссылке (assignment by reference) — это механизм, благодаря которому можно обратиться к контейнеру переменной и изменить его данные с помощью нескольких имен.

Давайте посмотрим на нашу символьную таблицу после выполнении присвоения по ссылке:

Как видите, значение is_ref = 1, благодаря этому после того как мы напишем $a = ‘changed text’ или $aa = ‘changed text’, получим следующий результат:

В отличии от присвоения по значению изменились данные и оба имени ($a и $aa) как указывали на эти данные, так и указывают, никакой новый контейнер для $aa не создался.

Если для приведенного выше кода выполнить unset($aa), тогда is_ref сбросится на 0 (это происходит только в том случае если больше нет дополнительных ссылок на данные, таких как $aa).

Передача ссылок в функцию

После передачи в функцию ссылок, имена во внутренней символьной таблице функции будут указывать на данные из внешней символьной таблицы:

1. $a = ‘some text’. Традиционно создается символьная таблица:

2. $b = myFunction($a). Создается временная символьная таблица функции и стек. Только is_ref теперь равен 1:

3. $var = ‘changed text’. Все имена куда указывали, туда и указывают, но данные изменились:

4. После выполнения операторов return $var; и $b = myFunction($a); имеем:

То есть, создается копия контейнера данных и $b указывает на эти данные.

5. Конец выполнения функции, очистка временной таблицы символов и стека функции, сбрасывание счетчика и значения is_ref в первом контейнере:

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

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

Простой пример использования:

Приведенный выше код выведет на экран строку “changed text”.

Еще один пример и “разбор полёта” (переменную $key мы не будем изображать на схемах ниже, она нас не интересует в данном случае):

1. $carList = array(‘audi’, ‘bmw’, ‘mazda’). На этом этапе глобальная символьная таблица имеет такой вид:

2. $car = &findCar(2, $carList). На этом этапе создается временная символьная таблица и стек функции, при этом is_ref для данных с массивом становится 1, а ref_count становится 3. Все так же, как это было в пункте 2, когда мы описывали передачу ссылок в функцию:

3. $item = &$cars[$key]. Теперь $item также находится во временной таблице символов (время жизни которой равно времени выполнения функции) и указывает на те же данные что и 2-й элемент массива:

4. После выполнения return $item; и $car = &findCar(2, $cars); Создается имя $car во внешней (глобальной) символьной таблице, которое указывает на данные (string) ‘mazda’, счетчик ref_count при этом увеличивается на 1:

5. Конец выполнения функции, очистка временной символьной таблицы, изменение соответствующих счетчиков ref_count и параметров is_ref:

6. $car = ‘subaru’. Изменение данных со (string) ‘mazda’ на (string) ‘subaru’. На эти данные сейчас указывает 2-й элемент массива $carList, а также ссылочная переменная $car:

Литература

1. PHP | Architect — June 2005. References in PHP — An In-Depth Look.

3. Язык программирования C (2-е издание). Брайан Керниган, Денис Ричи. Глава 5, Указатели и массивы.

Что такое ссылки 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.

<?php
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 позволяют создать две переменные указывающие на одно и то же значение. Таким образом, когда выполняется следующее:

Замечание:

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

Замечание:

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

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

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 :

Использование того же синтаксиса с функцией, которая не возвращает по ссылке, приведёт к ошибке, так же как и её использование с результатом оператора new. Хотя объекты передаются как указатели, это не то же самое, что ссылки, как описано в разделе Объекты и ссылки.

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

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

<?php
$var1 = «Пример переменной» ;
$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: ‘Пример переменной’
?>

Замечание:

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

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

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

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

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

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

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

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

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

User Contributed Notes 23 notes

I ran into something when using an expanded version of the example of pbaltz at NO_SPAM dot cs dot NO_SPAM dot wisc dot edu below.
This could be somewhat confusing although it is perfectly clear if you have read the manual carfully. It makes the fact that references always point to the content of a variable perfectly clear (at least to me).

<?php
$a = 1 ;
$c = 2 ;
$b =& $a ; // $b points to 1
$a =& $c ; // $a points now to 2, but $b still to 1;
echo $a , » » , $b ;
// Output: 2 1
?>

Watch out for this:

foreach ($somearray as &$i) <
// update some $i.
>
.
foreach ($somearray as $i) <
// last element of $somearray is mysteriously overwritten!
>

Problem is $i contians reference to last element of $somearray after the first foreach, and the second foreach happily assigns to it!

It appears that references can have side-effects. Below are two examples. Both are simply copying one array to another. In the second example, a reference is made to a value in the first array before the copy. In the first example the value at index 0 points to two separate memory locations. In the second example, the value at index 0 points to the same memory location.

I won’t say this is a bug, because I don’t know what the designed behavior of PHP is, but I don’t think ANY developers would expect this behavior, so look out.

An example of where this could cause problems is if you do an array copy in a script and expect on type of behavior, but then later add a reference to a value in the array earlier in the script, and then find that the array copy behavior has unexpectedly changed.

<?php
// Example one
$arr1 = array( 1 );
echo «\nbefore:\n» ;
echo «\$arr1[0] == < $arr1 [ 0 ]>\n» ;
$arr2 = $arr1 ;
$arr2 [ 0 ]++;
echo «\nafter:\n» ;
echo «\$arr1[0] == < $arr1 [ 0 ]>\n» ;
echo «\$arr2[0] == < $arr2 [ 0 ]>\n» ;

// Example two
$arr3 = array( 1 );
$a =& $arr3 [ 0 ];
echo «\nbefore:\n» ;
echo «\$a == $a \n» ;
echo «\$arr3[0] == < $arr3 [ 0 ]>\n» ;
$arr4 = $arr3 ;
$arr4 [ 0 ]++;
echo «\nafter:\n» ;
echo «\$a == $a \n» ;
echo «\$arr3[0] == < $arr3 [ 0 ]>\n» ;
echo «\$arr4[0] == < $arr4 [ 0 ]>\n» ;
?>

Something that might not be obvious on the first look:
If you want to cycle through an array with references, you must not use a simple value assigning foreach control structure. You have to use an extended key-value assigning foreach or a for control structure.

A simple value assigning foreach control structure produces a copy of an object or value. The following code

which means $v in foreach is not a reference to $v1 but a copy of the object the actual element in the array was referencing to.

and therefor cycle through the original objects (both $v1), which is, in terms of our aim, what we have been looking for.

(tested with php 4.1.3)

in PHP you don’t really need pointer anymore if you want to share an object across your program

<?php
class foo <
protected $name ;
function __construct ( $str ) <
$this -> name = $str ;
>
function __toString () <
return ‘my name is «‘ . $this -> name . ‘» and I live in «‘ . __CLASS__ . ‘».’ . «\n» ;
>
function setName ( $str ) <
$this -> name = $str ;
>
>

class MasterOne <
protected $foo ;
function __construct ( $f ) <
$this -> foo = $f ;
>
function __toString () <
return ‘Master: ‘ . __CLASS__ . ‘ | foo: ‘ . $this -> foo . «\n» ;
>
function setFooName ( $str ) <
$this -> foo -> setName ( $str );
>
>

class MasterTwo <
protected $foo ;
function __construct ( $f ) <
$this -> foo = $f ;
>
function __toString () <
return ‘Master: ‘ . __CLASS__ . ‘ | foo: ‘ . $this -> foo . «\n» ;
>
function setFooName ( $str ) <
$this -> foo -> setName ( $str );
>
>

$bar = new foo ( ‘bar’ );

print( «\n» );
print( «Only Created \$bar and printing \$bar\n» );
print( $bar );

print( «\n» );
print( «Now \$baz is referenced to \$bar and printing \$bar and \$baz\n» );
$baz =& $bar ;
print( $bar );

print( «\n» );
print( «Now Creating MasterOne and Two and passing \$bar to both constructors\n» );
$m1 = new MasterOne ( $bar );
$m2 = new MasterTwo ( $bar );
print( $m1 );
print( $m2 );

print( «\n» );
print( «Now changing value of \$bar and printing \$bar and \$baz\n» );
$bar -> setName ( ‘baz’ );
print( $bar );
print( $baz );

print( «\n» );
print( «Now printing again MasterOne and Two\n» );
print( $m1 );
print( $m2 );

print( «\n» );
print( «Now changing MasterTwo’s foo name and printing again MasterOne and Two\n» );
$m2 -> setFooName ( ‘MasterTwo\’s Foo’ );
print( $m1 );
print( $m2 );

print( «Also printing \$bar and \$baz\n» );
print( $bar );
print( $baz );
?>

In reply to lars at riisgaardribe dot dk,

When a variable is copied, a reference is used internally until the copy is modified. Therefore you shouldn’t use references at all in your situation as it doesn’t save any memory usage and increases the chance of logic bugs, as you discoved.

About the example on array references.
I think this should be written in the array chapter as well.
Indeed if you are new to programming language in some way, you should beware that arrays are pointers to a vector of Byte(s).

<?php $arr = array( 1 ); ?>
$arr here contains a reference to which the array is located.
Writing :
<?php echo $arr [ 0 ]; ?>
dereferences the array to access its very first element.

Now something that you should also be aware of (even you are not new to programming languages) is that PHP use references to contains the different values of an array. And that makes sense because the type of the elements of a PHP array can be different.

Consider the following example :

$arr = array( 1 , ‘test’ );

$point_to_test =& $arr [ 1 ];

$arr [ 1 ] =& $new_ref ;

echo $arr [ 1 ]; // echo ‘new’;
echo $point_to_test ; // echo ‘test’ ! (still pointed somewhere in the memory)

I think a correction to my last post is in order.

When there is a constructor, the strange behavior mentioned in my last post doesn’t occur. My guess is that php was treating reftest() as a constructor (maybe because it was the first function?) and running it upon instantiation.

<?php
class reftest
<
public $a = 1 ;
public $c = 1 ;

public function __construct ()
<
return 0 ;
>

public function reftest ()
<
$b =& $this -> a ;
$b ++;
>

$reference = new reftest ();

$reference -> reftest ();
$reference -> reftest2 ();

echo $reference -> a ; //Echoes 2.
echo $reference -> c ; //Echoes 2.
?>

Solution to post «php at hood dot id dot au 04-Mar-2007 10:56»:

foreach ( $a1 as $k =>& $v )
$v = ‘x’ ;

echo $a1 [ ‘a’ ]; // will echo x

unset( $GLOBALS [ ‘v’ ]);

foreach ( $a2 as $k => $v )
<>

echo $a1 [ ‘a’ ]; // will echo x

points to post below me.
When you’re doing the references with loops, you need to unset($var).

In this example class name is different from its first function and however there is no construction function. In the end as you guess «a» and «c» are equal. So if there is no construction function at same time class and its first function names are the same, «a» and «c» doesn’t equal forever. In my opinion php doesn’t seek any function for the construction as long as their names differ from each others.

<?php
class reftest_new
<
public $a = 1 ;
public $c = 1 ;

public function reftest ()
<
$b =& $this -> a ;
$b ++;
>

$reference = new reftest_new ();

$reference -> reftest ();
$reference -> reftest2 ();

echo $reference -> a ; //Echoes 2.
echo $reference -> c ; //Echoes 2.
?>

It matters if you are playing with a reference or with a value

Here we are working with values so working on a reference updates original variable too;

$b = & $a;
echo «$a, $b»; //Output: 1, 1

$b++;
echo «$a, $b»;//Output: 2, 2 both values are updated

$b = 10;
echo «$a, $b»;//Output: 10, 10 both values are updated

$b =$c; //This assigns value 2 to $b which also updates $a
echo «$a, $b»;//Output: 22, 22

But, if instead of $b=$c you do
$b = &$c; //Only value of $b is updated, $a still points to 10, $b serves now reference to variable $c

echo «$a, $b»//Output: 10, 22

The order in which you reference your variables matters.

<?php
$a1 = «One» ;
$a2 = «Two» ;
$b1 = «Three» ;
$b2 = «Four» ;

echo $a1 ; //Echoes «One»
echo $b1 ; //Echoes «One»

echo $a2 ; //Echoes «Four»
echo $b2 ; //Echoes «Four»
?>

If you set a variable before passing it to a function that takes a variable as a reference, it is much harder (if not impossible) to edit the variable within the function.

Example:
<?php
function foo (& $bar ) <
$bar = «hello\n» ;
>

foo ( $unset );
echo( $unset );
foo ( $set = «set\n» );
echo( $set );

It baffles me, but there you have it.

In reply to Drewseph using foo($a = ‘set’); where $a is a reference formal parameter.

$a = ‘set’ is an expression. Expressions cannot be passed by reference, don’t you just hate that, I do. If you turn on error reporting for E_NOTICE, you will be told about it.

Resolution: $a = ‘set’; foo($a); this does what you want.

Here’s a good little example of referencing. It was the best way for me to understand, hopefully it can help others.

When using references in a class, you can reference $this-> variables.

<?php
class reftest
<
public $a = 1 ;
public $c = 1 ;

public function reftest ()
<
$b =& $this -> a ;
$b = 2 ;
>

$reference = new reftest ();

$reference -> reftest ();
$reference -> reftest2 ();

echo $reference -> a ; //Echoes 2.
echo $reference -> c ; //Echoes 2.
?>

However, this doesn’t appear to be completely trustworthy. In some cases, it can act strangely.

<?php
class reftest
<
public $a = 1 ;
public $c = 1 ;

public function reftest ()
<
$b =& $this -> a ;
$b ++;
>

$reference = new reftest ();

$reference -> reftest ();
$reference -> reftest2 ();

echo $reference -> a ; //Echoes 3.
echo $reference -> c ; //Echoes 2.
?>

In this second code block, I’ve changed reftest() so that $b increments instead of just gets changed to 2. Somehow, it winds up equaling 3 instead of 2 as it should.

I discovered something today using references in a foreach

foreach ( $a1 as $k =>& $v )
$v = ‘x’ ;

echo $a1 [ ‘a’ ]; // will echo x

foreach ( $a2 as $k => $v )
<>

echo $a1 [ ‘a’ ]; // will echo b (!)
?>

After reading the manual this looks like it is meant to happen. But it confused me for a few days!

(The solution I used was to turn the second foreach into a reference too)

An interesting if offbeat use for references: Creating an array with an arbitrary number of dimensions.

For example, a function that takes the result set from a database and produces a multidimensional array keyed according to one (or more) columns, which might be useful if you want your result set to be accessible in a hierarchial manner, or even if you just want your results keyed by the values of each row’s primary/unique key fields.

<?php
function array_key_by ( $data , $keys , $dupl = false )
/*
* $data — Multidimensional array to be keyed
* $keys — List containing the index/key(s) to use.
* $dupl — How to handle rows containing the same values. TRUE stores it as an Array, FALSE overwrites the previous row.
*
* Returns a multidimensional array indexed by $keys, or NULL if error.
* The number of dimensions is equal to the number of $keys provided (+1 if $dupl=TRUE).
*/
<
// Sanity check
if (! is_array ( $data )) return null ;

// Allow passing single key as a scalar
if ( is_string ( $keys ) or is_integer ( $keys )) $keys = Array( $keys );
elseif (! is_array ( $keys )) return null ;

// Our output array
$out = Array();

// Loop through each row of our input $data
foreach( $data as $cx => $row ) if ( is_array ( $row ))
<

// Loop through our $keys
foreach( $keys as $key )
<
$value = $row [ $key ];

if (!isset( $last )) // First $key only
<
if (!isset( $out [ $value ])) $out [ $value ] = Array();
$last =& $out ; // Bind $last to $out
>
else // Second and subsequent $key.
<
if (!isset( $last [ $value ])) $last [ $value ] = Array();
>

// Bind $last to one dimension ‘deeper’.
// First lap: was &$out, now &$out[. ]
// Second lap: was &$out[. ], now &$out[. ][. ]
// Third lap: was &$out[. ][. ], now &$out[. ][. ][. ]
// (etc.)
$last =& $last [ $value ];
>

if (isset( $last ))
<
// At this point, copy the $row into our output array
if ( $dupl ) $last [ $cx ] = $row ; // Keep previous
else $last = $row ; // Overwrite previous
>
unset( $last ); // Break the reference
>
else return NULL ;

// A sample result set to test the function with
$data = Array(Array( ‘name’ => ‘row 1’ , ‘foo’ => ‘foo_a’ , ‘bar’ => ‘bar_a’ , ‘baz’ => ‘baz_a’ ),
Array( ‘name’ => ‘row 2’ , ‘foo’ => ‘foo_a’ , ‘bar’ => ‘bar_a’ , ‘baz’ => ‘baz_b’ ),
Array( ‘name’ => ‘row 3’ , ‘foo’ => ‘foo_a’ , ‘bar’ => ‘bar_b’ , ‘baz’ => ‘baz_c’ ),
Array( ‘name’ => ‘row 4’ , ‘foo’ => ‘foo_b’ , ‘bar’ => ‘bar_c’ , ‘baz’ => ‘baz_d’ )
);

// First, let’s key it by one column (result: two-dimensional array)
print_r ( array_key_by ( $data , ‘baz’ ));

// Or, key it by two columns (result: 3-dimensional array)
print_r ( array_key_by ( $data , Array( ‘baz’ , ‘bar’ )));

// We could also key it by three columns (result: 4-dimensional array)
print_r ( array_key_by ( $data , Array( ‘baz’ , ‘bar’ , ‘foo’ )));

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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