mirror of
https://github.com/sigmasternchen/php-doc-en
synced 2025-03-15 08:28:54 +00:00

This had a stray ")", and was left with a misleading half-sentence about "new" returning a reference, which it doesn't.
558 lines
16 KiB
XML
558 lines
16 KiB
XML
<?xml version="1.0" encoding="utf-8"?>
|
|
<!-- $Revision$ -->
|
|
<chapter xml:id="language.references" xmlns="http://docbook.org/ns/docbook">
|
|
<title>References Explained</title>
|
|
|
|
<sect1 xml:id="language.references.whatare">
|
|
<title>What References Are</title>
|
|
<simpara>
|
|
References in PHP are a means to access the same variable content
|
|
by different names. They are not like C pointers; for instance,
|
|
you cannot perform pointer arithmetic using them, they are not
|
|
actual memory addresses, and so on. See
|
|
<xref linkend="language.references.arent" /> for more
|
|
information. Instead, they are symbol table aliases. Note that in
|
|
PHP, variable name and variable content are different, so the same
|
|
content can have different names. The closest analogy is with
|
|
Unix filenames and files - variable names are directory entries,
|
|
while variable content is the file itself. References can be
|
|
likened to hardlinking in Unix filesystem.
|
|
</simpara>
|
|
</sect1>
|
|
|
|
<sect1 xml:id="language.references.whatdo">
|
|
<title>What References Do</title>
|
|
<para>
|
|
There are three basic operations performed using references:
|
|
<link linkend="language.references.whatdo.assign">assigning by
|
|
reference</link>, <link linkend="language.references.whatdo.pass">passing
|
|
by reference</link>,
|
|
and <link linkend="language.references.whatdo.return">returning by
|
|
reference</link>. This section will give an introduction to these
|
|
operations, with links for further reading.
|
|
</para>
|
|
<sect2 xml:id="language.references.whatdo.assign">
|
|
<title>Assign By Reference</title>
|
|
<para>
|
|
In the first of these, PHP references allow you to make two
|
|
variables refer to the same content. Meaning, when you do:
|
|
<informalexample>
|
|
<programlisting role="php">
|
|
<![CDATA[
|
|
<?php
|
|
$a =& $b;
|
|
?>
|
|
]]>
|
|
</programlisting>
|
|
</informalexample>
|
|
it means that <varname>$a</varname> and <varname>$b</varname>
|
|
point to the same content.
|
|
<note>
|
|
<para>
|
|
<varname>$a</varname> and <varname>$b</varname> are completely
|
|
equal here. <varname>$a</varname> is not pointing to
|
|
<varname>$b</varname> or vice versa.
|
|
<varname>$a</varname> and <varname>$b</varname> are pointing to the
|
|
same place.
|
|
</para>
|
|
</note>
|
|
</para>
|
|
<note>
|
|
<para>
|
|
If you assign, pass, or return an undefined variable by reference,
|
|
it will get created.
|
|
<example>
|
|
<title>Using references with undefined variables</title>
|
|
<programlisting role="php">
|
|
<![CDATA[
|
|
<?php
|
|
function foo(&$var) { }
|
|
|
|
foo($a); // $a is "created" and assigned to 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)
|
|
?>
|
|
]]>
|
|
</programlisting>
|
|
</example>
|
|
</para>
|
|
</note>
|
|
<para>
|
|
The same syntax can be used with functions that return
|
|
references:
|
|
<informalexample>
|
|
<programlisting role="php">
|
|
<![CDATA[
|
|
<?php
|
|
$foo =& find_var($bar);
|
|
?>
|
|
]]>
|
|
</programlisting>
|
|
</informalexample>
|
|
</para>
|
|
<para>
|
|
Using the same syntax with a function that does <emphasis>not</emphasis>
|
|
return by reference will give an error, as will using it with the result
|
|
of the <link linkend="language.oop5.basic.new">new</link> operator.
|
|
Although objects are passed around as pointers, these are not the same as references,
|
|
as explained under <link linkend="language.oop5.references">Objects and references</link>.
|
|
</para>
|
|
<warning>
|
|
<para>
|
|
If you assign a reference to a variable declared <literal>global</literal>
|
|
inside a function, the reference will be visible only inside the function.
|
|
You can avoid this by using the <varname>$GLOBALS</varname> array.
|
|
<example>
|
|
<title>Referencing global variables inside functions</title>
|
|
<programlisting role="php">
|
|
<![CDATA[
|
|
<?php
|
|
$var1 = "Example variable";
|
|
$var2 = "";
|
|
|
|
function global_references($use_globals)
|
|
{
|
|
global $var1, $var2;
|
|
if (!$use_globals) {
|
|
$var2 =& $var1; // visible only inside the function
|
|
} else {
|
|
$GLOBALS["var2"] =& $var1; // visible also in global context
|
|
}
|
|
}
|
|
|
|
global_references(false);
|
|
echo "var2 is set to '$var2'\n"; // var2 is set to ''
|
|
global_references(true);
|
|
echo "var2 is set to '$var2'\n"; // var2 is set to 'Example variable'
|
|
?>
|
|
]]>
|
|
</programlisting>
|
|
</example>
|
|
Think about <literal>global $var;</literal> as a shortcut to <literal>$var
|
|
=& $GLOBALS['var'];</literal>. Thus assigning another reference
|
|
to <literal>$var</literal> only changes the local variable's reference.
|
|
</para>
|
|
</warning>
|
|
<note>
|
|
<para>
|
|
If you assign a value to a variable with references in a
|
|
&foreach; statement, the references are modified too.
|
|
<example>
|
|
<title>References and foreach statement</title>
|
|
<programlisting role="php">
|
|
<![CDATA[
|
|
<?php
|
|
$ref = 0;
|
|
$row =& $ref;
|
|
foreach (array(1, 2, 3) as $row) {
|
|
// do something
|
|
}
|
|
echo $ref; // 3 - last element of the iterated array
|
|
?>
|
|
]]>
|
|
</programlisting>
|
|
</example>
|
|
</para>
|
|
</note>
|
|
<para>
|
|
While not being strictly an assignment by reference, expressions created
|
|
with the language construct
|
|
<link linkend="function.array"><literal>array()</literal></link> can also
|
|
behave as such by prefixing <literal>&</literal> to the array element
|
|
to add. Example:
|
|
<informalexample>
|
|
<programlisting role="php">
|
|
<![CDATA[
|
|
<?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); */
|
|
?>
|
|
]]>
|
|
</programlisting>
|
|
</informalexample>
|
|
</para>
|
|
<para>
|
|
Note, however, that references inside arrays are potentially dangerous.
|
|
Doing a normal (not by reference) assignment with a reference on the
|
|
right side does not turn the left side into a reference, but references
|
|
inside arrays are preserved in these normal assignments. This also applies
|
|
to function calls where the array is passed by value. Example:
|
|
<informalexample>
|
|
<programlisting role="php">
|
|
<![CDATA[
|
|
<?php
|
|
/* Assignment of scalar variables */
|
|
$a = 1;
|
|
$b =& $a;
|
|
$c = $b;
|
|
$c = 7; //$c is not a reference; no change to $a or $b
|
|
|
|
/* Assignment of array variables */
|
|
$arr = array(1);
|
|
$a =& $arr[0]; //$a and $arr[0] are in the same reference set
|
|
$arr2 = $arr; //not an assignment-by-reference!
|
|
$arr2[0]++;
|
|
/* $a == 2, $arr == array(2) */
|
|
/* The contents of $arr are changed even though it's not a reference! */
|
|
?>
|
|
]]>
|
|
</programlisting>
|
|
</informalexample>
|
|
In other words, the reference behavior of arrays is defined in an
|
|
element-by-element basis; the reference behavior of individual elements
|
|
is dissociated from the reference status of the array container.
|
|
</para>
|
|
</sect2>
|
|
<sect2 xml:id="language.references.whatdo.pass">
|
|
<title>Pass By Reference</title>
|
|
<para>
|
|
The second thing references do is to pass variables by
|
|
reference. This is done by making a local variable in a function
|
|
and a variable in the calling scope referencing the same
|
|
content. Example:
|
|
<informalexample>
|
|
<programlisting role="php">
|
|
<![CDATA[
|
|
<?php
|
|
function foo(&$var)
|
|
{
|
|
$var++;
|
|
}
|
|
|
|
$a=5;
|
|
foo($a);
|
|
?>
|
|
]]>
|
|
</programlisting>
|
|
</informalexample>
|
|
will make <varname>$a</varname> to be 6. This happens because in
|
|
the function <varname>foo</varname> the variable
|
|
<varname>$var</varname> refers to the same content as
|
|
<varname>$a</varname>. For more information on this, read
|
|
the <link linkend="language.references.pass">passing by
|
|
reference</link> section.
|
|
</para>
|
|
</sect2>
|
|
<sect2 xml:id="language.references.whatdo.return">
|
|
<title>Return By Reference</title>
|
|
<para>
|
|
The third thing references can do is <link
|
|
linkend="language.references.return">return by reference</link>.
|
|
</para>
|
|
</sect2>
|
|
</sect1>
|
|
|
|
<sect1 xml:id="language.references.arent">
|
|
<title>What References Are Not</title>
|
|
<para>
|
|
As said before, references are not pointers. That means, the
|
|
following construct won't do what you expect:
|
|
<informalexample>
|
|
<programlisting role="php">
|
|
<![CDATA[
|
|
<?php
|
|
function foo(&$var)
|
|
{
|
|
$var =& $GLOBALS["baz"];
|
|
}
|
|
foo($bar);
|
|
?>
|
|
]]>
|
|
</programlisting>
|
|
</informalexample>
|
|
</para>
|
|
<simpara>
|
|
What happens is that <varname>$var</varname> in
|
|
<varname>foo</varname> will be bound with
|
|
<varname>$bar</varname> in the caller, but then
|
|
re-bound with <varname>$GLOBALS["baz"]</varname>. There's no way
|
|
to bind <varname>$bar</varname> in the calling scope to something else
|
|
using the reference mechanism, since <varname>$bar</varname> is not
|
|
available in the function <varname>foo</varname> (it is represented by
|
|
<varname>$var</varname>, but <varname>$var</varname> has only
|
|
variable contents and not name-to-value binding in the calling
|
|
symbol table).
|
|
You can use <link linkend="language.references.return">returning
|
|
references</link> to reference variables selected by the function.
|
|
</simpara>
|
|
</sect1>
|
|
|
|
<sect1 xml:id="language.references.pass">
|
|
<title>Passing by Reference</title>
|
|
<para>
|
|
You can pass a variable by reference to a function so the function
|
|
can modify the variable. The syntax is as follows:
|
|
<informalexample>
|
|
<programlisting role="php">
|
|
<![CDATA[
|
|
<?php
|
|
function foo(&$var)
|
|
{
|
|
$var++;
|
|
}
|
|
|
|
$a=5;
|
|
foo($a);
|
|
// $a is 6 here
|
|
?>
|
|
]]>
|
|
</programlisting>
|
|
</informalexample>
|
|
<note>
|
|
<simpara>
|
|
There is no reference sign on a function call - only on
|
|
function definitions. Function definitions alone are enough to
|
|
correctly pass the argument by reference.
|
|
</simpara>
|
|
</note>
|
|
</para>
|
|
<para>
|
|
The following things can be passed by reference:
|
|
<itemizedlist>
|
|
<listitem>
|
|
<simpara>
|
|
Variables, i.e. <literal>foo($a)</literal>
|
|
</simpara>
|
|
</listitem>
|
|
<listitem>
|
|
<para>
|
|
References returned from functions, i.e.:
|
|
<informalexample>
|
|
<programlisting role="php">
|
|
<![CDATA[
|
|
<?php
|
|
function foo(&$var)
|
|
{
|
|
$var++;
|
|
}
|
|
function &bar()
|
|
{
|
|
$a = 5;
|
|
return $a;
|
|
}
|
|
foo(bar());
|
|
?>
|
|
]]>
|
|
</programlisting>
|
|
</informalexample>
|
|
See more about <link
|
|
linkend="language.references.return">returning by reference</link>.
|
|
</para>
|
|
</listitem>
|
|
</itemizedlist>
|
|
</para>
|
|
<para>
|
|
No other expressions should be passed by reference, as the
|
|
result is undefined. For example, the following examples of passing
|
|
by reference are invalid:
|
|
<informalexample>
|
|
<programlisting role="php">
|
|
<![CDATA[
|
|
<?php
|
|
function foo(&$var)
|
|
{
|
|
$var++;
|
|
}
|
|
function bar() // Note the missing &
|
|
{
|
|
$a = 5;
|
|
return $a;
|
|
}
|
|
foo(bar()); // Produces a notice
|
|
|
|
foo($a = 5); // Expression, not variable
|
|
foo(5); // Produces fatal error
|
|
|
|
class Foobar
|
|
{
|
|
}
|
|
|
|
foo(new Foobar()) // Produces a notice as of PHP 7.0.7
|
|
// Notice: Only variables should be passed by reference
|
|
?>
|
|
]]>
|
|
</programlisting>
|
|
</informalexample>
|
|
</para>
|
|
</sect1>
|
|
|
|
<sect1 xml:id="language.references.return">
|
|
<title>Returning References</title>
|
|
<para>
|
|
Returning by reference is useful when you want to use a function
|
|
to find to which variable a reference should be bound. Do
|
|
<emphasis>not</emphasis> use return-by-reference to increase performance.
|
|
The engine will automatically optimize this on its own. Only return
|
|
references when you have a valid technical reason to do so. To
|
|
return references, use this syntax:
|
|
<informalexample>
|
|
<programlisting role="php">
|
|
<![CDATA[
|
|
<?php
|
|
class foo {
|
|
public $value = 42;
|
|
|
|
public function &getValue() {
|
|
return $this->value;
|
|
}
|
|
}
|
|
|
|
$obj = new foo;
|
|
$myValue = &$obj->getValue(); // $myValue is a reference to $obj->value, which is 42.
|
|
$obj->value = 2;
|
|
echo $myValue; // prints the new value of $obj->value, i.e. 2.
|
|
?>
|
|
]]>
|
|
</programlisting>
|
|
</informalexample>
|
|
In this example, the property of the object returned by the
|
|
<varname>getValue</varname> function would be set, not the
|
|
copy, as it would be without using reference syntax.
|
|
</para>
|
|
<note>
|
|
<simpara>
|
|
Unlike parameter passing, here you have to use
|
|
<literal>&</literal> in both places - to indicate that you
|
|
want to return by reference, not a copy, and to indicate that
|
|
reference binding, rather than usual assignment, should be done
|
|
for <varname>$myValue</varname>.
|
|
</simpara>
|
|
</note>
|
|
<note>
|
|
<simpara>
|
|
If you try to return a reference from a function with the syntax:
|
|
<literal>return ($this->value);</literal> this will <emphasis>not</emphasis>
|
|
work as you are attempting to return the result of an
|
|
<emphasis>expression</emphasis>, and not a variable, by reference. You can
|
|
only return variables by reference from a function - nothing else.
|
|
</simpara>
|
|
</note>
|
|
<para>
|
|
To use the returned reference, you must use reference assignment:
|
|
<informalexample>
|
|
<programlisting role="php">
|
|
<![CDATA[
|
|
<?php
|
|
function &collector() {
|
|
static $collection = array();
|
|
return $collection;
|
|
}
|
|
$collection = &collector();
|
|
$collection[] = 'foo';
|
|
?>
|
|
]]>
|
|
</programlisting>
|
|
</informalexample>
|
|
To pass the returned reference to another function expecting a reference
|
|
you can use this syntax:
|
|
<informalexample>
|
|
<programlisting role="php">
|
|
<![CDATA[
|
|
<?php
|
|
function &collector() {
|
|
static $collection = array();
|
|
return $collection;
|
|
}
|
|
array_push(collector(), 'foo');
|
|
?>
|
|
]]>
|
|
</programlisting>
|
|
</informalexample>
|
|
</para>
|
|
<note>
|
|
<simpara>
|
|
Note that <literal>array_push(&collector(), 'foo');</literal> will
|
|
<emphasis>not</emphasis> work, it results in a fatal error.
|
|
</simpara>
|
|
</note>
|
|
</sect1>
|
|
|
|
<sect1 xml:id="language.references.unset">
|
|
<title>Unsetting References</title>
|
|
<para>
|
|
When you unset the reference, you just break the binding between
|
|
variable name and variable content. This does not mean that
|
|
variable content will be destroyed. For example:
|
|
<informalexample>
|
|
<programlisting role="php">
|
|
<![CDATA[
|
|
<?php
|
|
$a = 1;
|
|
$b =& $a;
|
|
unset($a);
|
|
?>
|
|
]]>
|
|
</programlisting>
|
|
</informalexample>
|
|
won't unset <varname>$b</varname>, just <varname>$a</varname>.
|
|
</para>
|
|
<simpara>
|
|
Again, it might be useful to think about this as analogous to the Unix
|
|
<command>unlink</command> call.
|
|
</simpara>
|
|
</sect1>
|
|
|
|
<sect1 xml:id="language.references.spot">
|
|
<title>Spotting References</title>
|
|
<simpara>
|
|
Many syntax constructs in PHP are implemented via referencing
|
|
mechanisms, so everything mentioned herein about reference binding also
|
|
applies to these constructs. Some constructs, like passing and
|
|
returning by reference, are mentioned above. Other constructs that
|
|
use references are:
|
|
</simpara>
|
|
|
|
<sect2 xml:id="references.global">
|
|
<title>global References</title>
|
|
<para>
|
|
When you declare a variable as <command>global $var</command> you
|
|
are in fact creating reference to a global variable. That means,
|
|
this is the same as:
|
|
<informalexample>
|
|
<programlisting role="php">
|
|
<![CDATA[
|
|
<?php
|
|
$var =& $GLOBALS["var"];
|
|
?>
|
|
]]>
|
|
</programlisting>
|
|
</informalexample>
|
|
</para>
|
|
<simpara>
|
|
This also means that unsetting <varname>$var</varname>
|
|
won't unset the global variable.
|
|
</simpara>
|
|
</sect2>
|
|
</sect1>
|
|
|
|
</chapter>
|
|
|
|
<!-- Keep this comment at the end of the file
|
|
Local variables:
|
|
mode: sgml
|
|
sgml-omittag:t
|
|
sgml-shorttag:t
|
|
sgml-minimize-attributes:nil
|
|
sgml-always-quote-attributes:t
|
|
sgml-indent-step:1
|
|
sgml-indent-data:t
|
|
indent-tabs-mode:nil
|
|
sgml-parent-document:nil
|
|
sgml-default-dtd-file:"~/.phpdoc/manual.ced"
|
|
sgml-exposed-tags:nil
|
|
sgml-local-catalogs:nil
|
|
sgml-local-ecat-files:nil
|
|
End:
|
|
vim600: syn=xml fen fdm=syntax fdl=2 si
|
|
vim: et tw=78 syn=sgml
|
|
vi: ts=1 sw=1
|
|
-->
|