|
 |
Ссылки в PHP дают возможность двум переменным ссылаться на одно содержимое. Например:
означает, что $a указывает на то же содержание, что и $b.
Замечание:
$a и $b здесь абсолютно эквивалентны, но это не означает, что $a указывает на $b или наоборот. Это означает, что $a и $b указывают на одно место.
Замечание:
При копировании массива ссылок, они не разыменовываются.
Это также касается массивов, передаваемых функциям по значению.
Такой же синтаксис можно использовать и в функциях, возвращая ссылки, а так же в операторе new (начиная с PHP 4.0.4):
Замечание:
Если опустить &, это приведёт к копированию объекта.
Если вы используете $this в классе, операция проводится над текущим экземпляром этого класса.
Присвоение без & приведёт к копированию экземпляра, и $this будет работать с копией, что не всегда желательно.
Обычно, вам нужно иметь один экземпляр, из соображений производительности и использования памяти.
Операция @, которая скрывает сообщения об ошибках, например в конструкторе @new, не может быть использована совместно с операцией & (&new).
Это ограничение интерпретатора Zend.
Внимание |
Если переменной, объявленной внутри функции как global, будет присвоена ссылка, она будет видна только в функции.
Чтобы избежать это, воспользуйтесь массивом $GLOBALS.
Пример 21-1. Присвоение ссылок глобальным переменным внутри функции
<?php
$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"; global_references(true);
echo "значение var2: '$var2'\n"; ?>
|
|
Думайте о global $var; как о сокращении от $var =& $GLOBALS['var'];. Таким образом, присвоение $var другой ссылки влияет лишь на локальную переменную.
|
Замечание:
При использовании переменной-ссылки в foreach,
изменяется содержание, на которое она ссылается.
Пример 21-2. Ссылки и foreach
<?php
$ref = 0;
$row =& $ref;
foreach (array(1, 2, 3) as $row) {
}
echo $ref; ?>
|
|
Внимание |
Сложные массивы в некоторых случаях могут копироваться вместо создания ссылок. например, следующий пример не будет работать как ожидалось.
Пример 21-3. Ссылки и сложные массивы
<?php
$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']); ?>
|
|
|
Второе, что делают ссылки - передача параметров по ссылке.
При этом локальная переменная в функции и переменная в области видимости вызывателя ссылаются на одно и то же содержимое.
Пример:
Этот код присвоит $a значение 6. Это происходит, потому что в функции foo переменная $var ссылается на то же содержимое, что и переменная $a. См. также детальное объяснение передачи по ссылке.
Третье, что могут ссылк - возвращение значение по ссылке.
Что делают ссылки
chat~kaptain524 at neverbox dot com
24-Aug-2005 09:15
Example 21-3 says that using references in "complex arrays" may not work as expected. But I have found a way around it, to get normal reference behavior.
Compare the output of these two scripts:
<?php
for ( $i = 0; $i < 10; $i ++ ) $top[$i] = &$top;
$top['A'] = 'AAAAA'; var_dump( $top );
?>
<?php
$z = &$top;
for ( $i = 0; $i < 10; $i ++ ) $top[$i] = &$top;
$top['A'] = 'AAAAA'; var_dump( $top );
?>
Running PHP 5.0, the first generates about 157457 lines while the second only generates 2554 lines. The only difference in the code is setting an initial reference before adding self-references inside the array. This simple step prevents the array from being duplicated every time another self-reference is added.
I am not sure if the duplication is intentional or if it's a bug in the way references are created, but the docs certainly recognize it.
+CurTis-
23-May-2005 12:15
I know that most everyones' comments are really insightful and many have exceptional PHP code to share, but I just wanted to point out a nice little method for situations where you are not sure what your variables contain exactly.
When developing, and you hit a wall debugging, be sure to echo your variable's contents at various stages of your script, so you can more easily track down where your problem is occurring. This is especially helpful when in a complicated referencing situation (like ladoo at gmx dot at's situation below). Also, be sure to make use of print_r, it is a life-saver!
Take care,
+CurTis-
curtis
23-May-2005 12:13
I know that most everyones' comments are really insightful and many have exceptional PHP code to share, but I just wanted to point out a nice little method for situations where you are not sure what your variables contain exactly.
When developing, and you hit a wall debugging, be sure to echo your variable's contents at various stages of your script, so you can more easily track down where your problem is occurring. This is especially helpful when in a complicated referencing situation (like ladoo at gmx dot at's situation below). Also, be sure to make use of print_r, it is a life-saver!
Take care,
+CurTis-
curtis
23-May-2005 12:12
I know that most everyones' comments are really insightful and many have exceptional PHP code to share, but I just wanted to point out a nice little method for situations where you are not sure what your variables contain exactly.
When developing, and you hit a wall debugging, be sure to echo your variable's contents at various stages of your script, so you can more easily track down where your problem is occurring. This is especially helpful when in a complicated referencing situation (like ladoo at gmx dot at's situation below). Also, be sure to make use of print_r, it is a life-saver!
Take care,
+CurTis-
ladoo at gmx dot at
17-Apr-2005 02:05
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; $a =& $c; echo $a, " ", $b;
?>
miqrogroove
21-Mar-2005 01:40
More on references and globals:
String variables are not automatically passed by reference in PHP. Some other languages, such as Visual Basic, will do that automatically for all variables. PHP will not.
Consider the case where a function receives a global variable as a parameter and also has the same variable defined locally with the 'global' statement. Do the parameter and global variable now reference the same memory?
No, they do not! Passing the global variable into the function as a parameter caused a second variable to be created by default.
Here is an example of this scenario:
<?php
$teststring="Hello";
one();
function one(){
global $teststring;
two($teststring);
echo $teststring; }
function two($param){
global $teststring;
$teststring="World";
echo $param; $param="Clear?";
}
?>
Enjoy
x123 t bestof dsh inter dt net
14-Dec-2004 02:42
It might be worth to note that a reference can be created to an unexisting variable, the reference is then "undefined" (NOT isset()) but when the other variable is created, the reference also gets "isset":
<?= phpversion(),
aa, isset($gg), bb, $a=&$GLOBALS[gg], isset($gg),cc,
isset($a),dd, $gg=ee, isset($gg),ff, isset($a),hh, $a
?>
prints
4.2.0RC2aabbccddee1ff1hhee
As I did not find anything about this "feature" in the doc, maybe better don't rely on it.
(but where the heck is this "undefined" reference living while it is not set ?)
php.devel at homelinkcs dot com
15-Nov-2004 03:16
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.
lars at riisgaardribe dot dk
19-Jul-2004 04:49
A comment to pbaltz at NO_SPAM dot cs dot NO_SPAM dot wisc dot edu:
The following code did not work as I expected either:
while ( $row = mysql_fetch_array( $result ) ) {
// ... do something ...
// Now store the array $row in an array containing all rows.
$result_array[] = &$row; // I dont want to copy - there is a lot of data in $row
}
var_dump ( $result_array ) shows that all stored values now are "false" as this is the last value of $row.
Instead the code should be:
while ( $row = mysql_fetch_array( $result ) ) {
// ... do something ...
$result_array[] = &$row;
unset ( $row ); //breaks the linkage between $row and a line in $result_array
}
Hope this is understandable/usefull
phpmaster a#t cybercow #se=
20-May-2004 10:15
Regarding to what "todd at nemi dot net" said, that you don't need to add an ampersand on code like this, because you get the same result without it.
function myClass() {
//...some code...
return $this;
}
$myObj =& new myClass()
I just experienced something else. I have a pretty complicated/large class relation ship in one part of our software. And when I didn't enter the ampersand I got a totally different result from my function, an array from a totaly different array.
So my suggestion is that you enter the ampersand so it looks like this.
function &getError()
{
return $this->systemError;
}
$errors = & $connection->getError();
agggka at hotmail dot com
18-Feb-2004 06:49
to jazfresh at hotmail dot com (comments from 17-Feb-2004)
You don't really need array_keys()
<?
function &findMyObjectByName($name)
{
foreach ($this->my_array as $key => $obj)
{
if (0 == strcmp($name, $obj->getName()))
{ return ($my_array[$key]); }
}
return (null); }
?>
jazfresh at hotmail dot com
17-Feb-2004 03:39
Say you want to search an array, with the intention of returning a reference to the value (so that the parent function can directly edit the array element). You cannot use "foreach" or "each" in the traditional way, because those functions will make a copies of the object, rather than return references to the original array element.
<?
function &findMyObjectByName($name) {
foreach($this->my_array as $obj) {
if($obj->getName() == $name) {
return $obj;
}
}
return null; }
?>
To avoid this pitfall, use array_keys():
<?
function &findMyObjectByName($name) {
foreach(array_keys($this->my_array) as $key) {
if($this->my_array[$key]->getName() == $name) {
return $my_array[$key];
}
}
return null; }
?>
php-doc-21-may-2003 at ryandesign dot com
21-May-2003 06:34
To Jeb in regard to his comment from March 2003, the easier way to handle your situation -- the possibility that the server will have an older version of PHP which doesn't support $_GET -- is to include the following at the top of every page:
if (!isset($_GET)) $_GET =& $GLOBALS['HTTP_GET_VARS'];
Then just use $_GET everywhere as usual.
joachim at lous dot org
10-Apr-2003 03:46
So to make a by-reference setter function, you need to specify reference semantics _both_ in the parameter list _and_ the assignment, like this:
class foo{
var $bar;
function setBar(&$newBar){
$this->bar =& newBar;
}
}
Forget any of the two '&'s, and $foo->bar will end up being a copy after the call to setBar.
todd at nemi dot net
11-Feb-2002 11:15
tbutzon@imawebdesigner.com Makes an excellent point in his reference examples, however, what you find in practice is that you do not need the & in the function definition to actually assign the reference. It is redundant.
The proper way to return a reference is by using:
function &myClass() {
//...some code...
return $this;
}
$myObj =& new myClass()
...however, this produces the exact same result:
function myClass() {
//...some code...
return $this;
}
$myObj =& new myClass()
Apparently, the Ampersand on the assignment is all that is really needed for a reference to truly be assigned. The Ampersand on the function definition actually does nothing.
pbaltz at NO_SPAM dot cs dot NO_SPAM dot wisc dot edu
01-May-2001 01:02
Just a note for others who may run into this. When the manual says that references are bound to the same copy of the content, it means exactly that.
So doing something like this,
$a = 1;
$b =& $a;
$b = 2;
print "$a $b";
will print '2 2'. This can be frustrating to track down if, like me, you are used to Perl where you explicitly dereference refrences. Since $a and $b both reference the same data, changing either, changes both.
It may be obvious to others, but if you are familiar with pointers or Perl references the automatic dereferencing can be confusing if you forget about it.
| |