1
0
mirror of https://github.com/php/doc-es.git synced 2026-03-25 16:02:13 +01:00
Files
archived-doc-es/language/references.xml
Pedro Antonio Gil Rodríguez 23b2de887a Actualización a la última versión
git-svn-id: https://svn.php.net/repository/phpdoc/es/trunk@337320 c90b9560-bf6c-de11-be94-00142212c4b1
2015-08-07 10:29:03 +00:00

581 lines
18 KiB
XML

<?xml version="1.0" encoding="utf-8"?>
<!-- $Revision$ -->
<!-- EN-Revision: 97c50278a64ae5e3e646e36c1f7926c1bb2e689a Maintainer: seros Status: ready -->
<!-- Reviewed: no Maintainer: yago -->
<chapter xml:id="language.references" xmlns="http://docbook.org/ns/docbook">
<title>Referencias Explicadas</title>
<sect1 xml:id="language.references.whatare">
<title>¿Qué son las Referencias?</title>
<simpara>
Las Referencias en PHP son medios de acceder al mismo contenido de una variable
mediante diferentes nombres. No son como los punteros de C; por ejemplo,
no se puede realizar aritmética de punteros con ellas, realmente
no son direcciones de memoria, etc. Véase
<xref linkend="language.references.arent" /> para más
información. Las referencias son alias de la tabla de símbolos. Observe que en
PHP el nombre de la variable y el contenido de la variable son cosas diferentes, por lo que el mismo
contenido puede tener diferentes nombres. La analogía más próxima es con
los archivos y los nombres de archivos de Unix - los nombres de variables son entradas de directorio,
mientras que el contenido de las variables es el archivo en sí. Las referencias se pueden
vincular a enlaces duros en sistemas de archivos Unix.
</simpara>
</sect1>
<sect1 xml:id="language.references.whatdo">
<title>¿Qué hacen las referencias?</title>
<para>
Hay tres operaciones básicas que se realizan usando referencias:
<link linkend="language.references.whatdo.assign">asignar por
referencia</link>, <link linkend="language.references.whatdo.pass">pasar por
referencia</link>,
y <link linkend="language.references.whatdo.return">devolver por
referencia</link>. En esta sección se dará una introducción a estas
operaciones, con enlaces para una lectura complementaria.
</para>
<sect2 xml:id="language.references.whatdo.assign">
<title>Asignar por Referencia</title>
<para>
En la primera de estas operaciones, las referencias de PHP permiten hacer que dos
variables hagan referencia al mismo contenido. Es decir, cuando se hace:
<informalexample>
<programlisting role="php">
<![CDATA[
<?php
$a =& $b;
?>
]]>
</programlisting>
</informalexample>
significa que <varname>$a</varname> y <varname>$b</varname>
apuntan al mismo contenido.
<note>
<para>
<varname>$a</varname> y <varname>$b</varname> aquí son completamente
iguales. <varname>$a</varname> no está apuntando a
<varname>$b</varname> o viceversa.
<varname>$a</varname> y <varname>$b</varname> están apuntando al
mismo lugar.
</para>
</note>
</para>
<note>
<para>
Si se asigna, pasa, o devuelve una variable no definida por referencia,
la variable se creará.
<example>
<title>Usar referencias con variables no definidas</title>
<programlisting role="php">
<![CDATA[
<?php
function foo(&$var) { }
foo($a); // $a es "creada" y asignada 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)
?>
]]>
</programlisting>
</example>
</para>
</note>
<para>
Se puede usar la misma sintaxis con funciones que devuelven
referencias y con el operador <literal>new</literal> (desde PHP
4.0.4 y anterior a PHP 5.0.0):
<informalexample>
<programlisting role="php">
<![CDATA[
<?php
$foo =& find_var($bar);
?>
]]>
</programlisting>
</informalexample>
Desde PHP 5, <link linkend="language.oop5.basic.new">new</link>
devuelve una referencia automáticamente, por lo que
usar <literal>=&amp;</literal> en este contexto es obsoleto y
produce un mensaje <constant>E_DEPRECATED</constant> en PHP 5.3 y
posteriores, y un mensaje <constant>E_STRICT</constant> en versiones anteriores.
A partir de PHP 7.0 es sintácticamente inválido.
(Técnicamente, la diferencia es que, en PHP 5, las variables de objetos, como
los recursos, son meros punteros a la información del objeto actual, por lo que estas referencias
a objetos no son "referencias" en el mismo sentido usado antes (alias).
Para más información, véase <link linkend="language.oop5.references">Objetos
y referencias</link>.)
</para>
<warning>
<para>
Si se asigna una referencia a una varible declarada <literal>global</literal>
dentro de una función, la referencia será visible sólo dentro de la función.
Se puede evitar esto usando la matriz <varname>$GLOBALS</varname>.
<example>
<title>Refenciar variables globales dentro de funciones</title>
<programlisting role="php">
<![CDATA[
<?php
$var1 = "Variable de ejemplo";
$var2 = "";
function referencias_globales($usar_globals)
{
global $var1, $var2;
if (!$usar_globals) {
$var2 =& $var1; // visible sólo dentro de la función
} else {
$GLOBALS["var2"] =& $var1; // visible también en el contexto global
}
}
referencias_globales(false);
echo "var2 está establecida a '$var2'\n"; // var2 está establecida a ''
referencias_globales(true);
echo "var2 está establecida a '$var2'\n"; // var2 está establecida a 'Variable de ejemplo'
?>
]]>
</programlisting>
</example>
Piense en <literal>global $var;</literal> como simplificación de <literal>$var
=&amp; $GLOBALS['var'];</literal>. De este modo, al asignar otra referencia
a <literal>$var</literal> sólo cambia la referencia de la variable local.
</para>
</warning>
<note>
<para>
Si se asigna un valor a una variable con referencias en una
sentencia &foreach;, también se modifican las referencias.
<example>
<title>Referencias y la sentencia foreach</title>
<programlisting role="php">
<![CDATA[
<?php
$ref = 0;
$fila =& $ref;
foreach (array(1, 2, 3) as $fila) {
// hacer algo
}
echo $ref; // 3 - último elemento de la matriz iterada
?>
]]>
</programlisting>
</example>
</para>
</note>
<para>
Mientras que no sea estrictamente una asignación por referencia, las expresiones creadas
con el constructor de lenguaje
<link linkend="function.array"><literal>array()</literal></link> también pueden
comportarse como tales prefijando <literal>&amp;</literal> al elemento del array
a añadir. Ejemplo:
<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>
Observe, sin embargo, que las referencias dentro de arrays son potencialmente peligrosas.
Realizar una asignación normal (no por referencia) con una referencia en el
lado derecho no convierte el lado izquierdo en una referencia, pero las referencias
dentro de arrays son conservadas en estas asignaciones normales. Esto también se aplica
a las llamadas a funciones donde el array es pasado por valor. Ejemplo:
<informalexample>
<programlisting role="php">
<![CDATA[
<?php
/* Asignación de variables escalares */
$a = 1;
$b =& $a;
$c = $b;
$c = 7; //$c no es una referencia; no cambia $a o $b
/* Asignación de variables de array */
$arr = array(1);
$a =& $arr[0]; // $a y $arr[0] son el mismo conjunto de referencias
$arr2 = $arr; // ¡no es una asignación por referencia!
$arr2[0]++;
/* $a == 2, $arr == array(2) */
/* ¡El contenido de $arr se cambia incluso si no es una referencia! */
?>
]]>
</programlisting>
</informalexample>
En otras palabras, el comportamiento de las referencias de arrays está definido en una
base elemento-por-elemento; el comportamiento de las referencias de elementos individuales
está desasociado del estado de la referencia del array contenedor.
</para>
</sect2>
<sect2 xml:id="language.references.whatdo.pass">
<title>Pasar por Referencia</title>
<para>
Lo segundo que hacen las referencias es pasar variables por
referencia. Esto se lleva a cabo haciendo que una variable local en una función
y una variable en el ámbito de la llamada referencien al mismo
contenido. Ejemplo:
<informalexample>
<programlisting role="php">
<![CDATA[
<?php
function foo(&$var)
{
$var++;
}
$a=5;
foo($a);
?>
]]>
</programlisting>
</informalexample>
hará que <varname>$a</varname> sea 6. Esto sucede porque en
la función <varname>foo</varname> la variable
<varname>$var</varname> hace referencia al mismo contenido que
<varname>$a</varname>. Para más información sobre esto, lea
la sección <link linkend="language.references.pass">pasar por
referencia</link>.
</para>
</sect2>
<sect2 xml:id="language.references.whatdo.return">
<title>Devolver por Referencia</title>
<para>
Lo tercero que hacen las referncias es <link
linkend="language.references.return">devolver por referencia</link>.
</para>
</sect2>
</sect1>
<sect1 xml:id="language.references.arent">
<title>¿Qué NO son las Referencias?</title>
<para>
Como se dijo antes, las referencias no son punteros. Es decir, la
siguiente construcción no hará lo que se esperaba:
<informalexample>
<programlisting role="php">
<![CDATA[
<?php
function foo(&$var)
{
$var =& $GLOBALS["baz"];
}
foo($bar);
?>
]]>
</programlisting>
</informalexample>
</para>
<simpara>
Lo que sucede es que <varname>$var</varname> en
<varname>foo</varname> será ligada con
<varname>$bar</varname> en la llamada, pero entonces
será religada con <varname>$GLOBALS["baz"]</varname>. No hay forma
de ligar <varname>$bar</varname> en el ámbito de la llamada a otra cosa
usando el mecanismo de referencia, ya que <varname>$bar</varname> no está
disponible en la función <varname>foo</varname> (está representada por
<varname>$var</varname>, pero <varname>$var</varname> sólo tiene
el contenido de la variable y no la vinculación nombre-a-valor en la tabla
de símbolos de llamada).
Se puede usar <link linkend="language.references.return">devolver
referencias</link> para referencias variables seleccionadas por la función.
</simpara>
</sect1>
<sect1 xml:id="language.references.pass">
<title>Pasar por Referencia</title>
<para>
Se puede pasar una variable por referencia a una función y así hacer que la función
pueda modificar la variable. La sintaxis es la siguiente:
<informalexample>
<programlisting role="php">
<![CDATA[
<?php
function foo(&$var)
{
$var++;
}
$a=5;
foo($a);
// $a es 6 aquí
?>
]]>
</programlisting>
</informalexample>
<note>
<simpara>
No existe ningún signo de referencia en una llamada a una función - sólo en
la definición de la función. Las definiciones de funciones por sí solas son suficientes para
pasar correctamente el argumento por referencia. A partir de PHP 5.3.0,
se obtendrá una advertencia diciendo que "call-time pass-by-reference" (pasar por referencia
en tiempo de llamada) está obsoleto cuando se use &amp; en <literal>foo(&amp;$a);</literal>.
A partir de PHP 5.4.0, el paso por referencia en tiempo de llamada ha sido eliminado,
por lo que su uso emitirá un error fatal.
</simpara>
</note>
</para>
<para>
Se puede pasar por referencia lo siguiente:
<itemizedlist>
<listitem>
<simpara>
Variables, esto es, <literal>foo($a)</literal>
</simpara>
</listitem>
<listitem>
<simpara>
Nuevas declaraciones, esto es, <literal>foo(new foobar())</literal>
</simpara>
</listitem>
<listitem>
<para>
Referencias devueltas desde funciones, esto es:
<informalexample>
<programlisting role="php">
<![CDATA[
<?php
function foo(&$var)
{
$var++;
}
function &bar()
{
$a = 5;
return $a;
}
foo(bar());
?>
]]>
</programlisting>
</informalexample>
Vea más sobre <link
linkend="language.references.return">devolver por referencia</link>.
</para>
</listitem>
</itemizedlist>
</para>
<para>
Ninguna otra expresión debería pasarse por referencia, ya que el
resultado no está definido. Por ejemplo, los siguientes ejemplos de pasar
por referencia no son válidos:
<informalexample>
<programlisting role="php">
<![CDATA[
<?php
function foo(&$var)
{
$var++;
}
function bar() // Observe que falta el &
{
$a = 5;
return $a;
}
foo(bar()); // Produce un error fatal a partir de PHP 5.0.5,un aviso de estándar estricto
// a partir de PHP 5.1.1, y un aviso a partir de PHP 7.0.0
foo($a = 5); // Expresión, no una variable
foo(5); // Produce un error fatal
?>
]]>
</programlisting>
</informalexample>
Estos requerimientos son para PHP 4.0.4 y posterior.
</para>
</sect1>
<sect1 xml:id="language.references.return">
<title>Devolver Referencias</title>
<para>
Devolver por referencia es útil cuando se quiere usar una función
para encontrar a qué variable debería estar vinculada una referencia.
<emphasis>No</emphasis> use devolver por referencia para aumentar el rendimiento.
El motor optimizará automáticamente esto por sí mismo. Hay que devolver
referencias sólo cuando se tenga una razón técnicamente válida para hacerlo. Para
devolver referencias use esta sintaxis:
<informalexample>
<programlisting role="php">
<![CDATA[
<?php
class foo {
public $valor = 42;
public function &obtenerValor() {
return $this->valor;
}
}
$obj = new foo;
$miValor = &$obj->obtenerValor(); // $miValor es una referencia a $obj->valor, que es 42.
$obj->valor = 2;
echo $miValor; // imprime el nuevo valor de $obj->valor, esto es, 2.
?>
]]>
</programlisting>
</informalexample>
En este ejemplo, la propiedad del objeto devuelto por la
función <varname>obtenerValor</varname> debería estar establecida, no la
copia, como si estuviera sin usar la sintaxis de referencia.
</para>
<note>
<simpara>
A diferencia de pasar un parámetro, aquí se tiene que usar
<literal>&amp;</literal> en ambos lugares - para indicar que se
quiere devolver por referencia, no una copia, y para indicar que
la vinculación por referencia, en vez de la asignación normal, debería ser hecha
para <varname>$miValor</varname>.
</simpara>
</note>
<note>
<simpara>
Si se intenta devolver una referencia desde una función con la sintaxis:
<literal>return ($this->valor);</literal>, <emphasis>no</emphasis>
funcionará ya que se está intentando devolver el resultado de una
<emphasis>expresión</emphasis>, y no de una variable, por referencia. Sólo se
puede devolver variables por referencia desde una función - nada más.
Desde PHP 4.4.0 en la rama PHP 4, y PHP 5.1.0 en la rama PHP 5, se
emite un error <constant>E_NOTICE</constant> si el código intenta devolver
una expresión dinámica o un resultado del operador <literal>new</literal>.
</simpara>
</note>
<para>
Para usar la referencia retornada, se debe usar la asignación por referencia:
<informalexample>
<programlisting role="php">
<![CDATA[
<?php
function &collector() {
static $collection = array();
return $collection;
}
$collection = &collector();
$collection[] = 'foo';
?>
]]>
</programlisting>
</informalexample>
Para pasar la referencia retornada a otra función que espera una referencia
se puede usar la siguiente sintaxis:
<informalexample>
<programlisting role="php">
<![CDATA[
<?php
function &collector() {
static $collection = array();
return $collection;
}
array_push(collector(), 'foo');
?>
]]>
</programlisting>
</informalexample>
</para>
<note>
<simpara>
Observe que <literal>array_push(&amp;collector(), 'foo');</literal>
<emphasis>no</emphasis> funcionará, resultará en un error fatal.
</simpara>
</note>
</sect1>
<sect1 xml:id="language.references.unset">
<title>Destruir Referencias</title>
<para>
Cuando se destruye una referencia, se rompe el vínculo entre
el nombre de la variable y el contenido de la variable. Esto no significa que
el contenido de la variable sea destruida. Por ejemplo:
<informalexample>
<programlisting role="php">
<![CDATA[
<?php
$a = 1;
$b =& $a;
unset($a);
?>
]]>
</programlisting>
</informalexample>
no destruirá <varname>$b</varname>, sólo <varname>$a</varname>.
</para>
<simpara>
De nuevo, podría ser útil pensar en esto como análogo a una llamada
a <command>unlink</command> de Unix.
</simpara>
</sect1>
<sect1 xml:id="language.references.spot">
<title>Ubicar las Referencias</title>
<simpara>
Muchas construcciones sintácticas de PHP están implementadas mediante el mecanismo
de referencia, por lo que todo lo mencionado aquí sobre la vinculación de referencias también
se aplica a estas construcciones. Algunas construcciones, como pasar y
devolver por referencia, han sido mencionadas antes. Otras construcciones que
usan referencias son:
</simpara>
<sect2 xml:id="references.global">
<title>Referencias globales</title>
<para>
Cuando se declara una variable como <command>global $var</command>,
de hecho se está creando una referencia a una variable global. Es decir,
esto es lo mismo que:
<informalexample>
<programlisting role="php">
<![CDATA[
<?php
$var =& $GLOBALS["var"];
?>
]]>
</programlisting>
</informalexample>
</para>
<simpara>
Esto también significa que al destruir <varname>$var</varname>
no se destruirá la variable global.
</simpara>
</sect2>
<sect2 xml:id="references.this">
<title><literal>$this</literal></title>
<simpara>
En un método de un objeto, <varname>$this</varname> es siempre una referencia
al objeto que realiza la llamada.
</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
-->