La razón por la que diferentes artículos parecen decir cosas diferentes es que hablan de diferentes tipos de paso por referencia.
Lo principal que determina si un parámetro debe pasarse por referencia es la firma de la función en sí, y los fundamentos de esto no han cambiado desde PHP 4.Considere este ejemplo:
function foo( $by_value, &$by_reference ) { /* ... */ }
$a = 1; $b = 2;
foo( $a, $b );
Aquí, la variable exterior $a
se pasa a la función por valor, como si se asignara como $by_value = $a;
- cambios a $by_value
no puede afectar $a
.La variable $b
sin embargo se está pasando por referencia;como una asignación de la forma $by_reference =& $b;
esto significa que hay una variable a la que hacen referencia dos nombres, y cualquier asignación a una actuará como una asignación a ambas.
Si pasa un valor "ordinario" (una cadena, número o matriz) por valor, su valor simplemente se copia en la nueva variable. A partir de PHP 5:Sin embargo, si pasa un objeto por valor, sucede algo ligeramente diferente: el "valor" copiado es solo un puntero al mismo objeto.Esto significa que si $a
Si fueras un objeto, podrías llamarlo $by_value->some_property = 42;
y $a->some_property
también sería 42
.Sin embargo, si asigna algún valor nuevo a $by_value
, todavía no afectaría $a
.
Hasta PHP 5.4, había un extra forma de pasar un parámetro por referencia, que era "forzar" el comportamiento de referencia en el momento de la llamada.Esto significaba que podías escribir foo(&$a, &$b);
y "capturar" los cambios realizados en $by_value
dentro de foo()
función.Confiar en esto era generalmente una mala idea, por lo que se eliminó.(Aterrizó en 5.4 porque estaba previsto que se eliminara en PHP 6, pero ese proyecto quedó en suspenso indefinidamente, y los cambios más pequeños llegaron a 5.3 y 5.4).
Finalmente, las funciones pueden devolver una variable por referencia (como discutido en el manual aquí).Esto es un poco complicado, ya que en realidad requiere que pongas &
en dos lugares:al comienzo de la declaración de función, para decir que return
debería significar "devolver esta referencia de variable", no "devolver este valor";y en el código que lo llama, asignar una variable a esa referencia, en lugar de simplemente copiar su valor.Aquí hay un ejemplo tonto que combina un parámetro de referencia con un retorno de referencia (los dos no tienen que ir juntos, es solo un ejemplo):
function &bar(&$some_param) { return $some_param; }
$a = 1;
$b =& bar($a);
// $b and $a now point at the same variable, not just the same value
// it was passed into and out of a function, and assigned to a new variable,
// but all those operations were by reference
Tenga en cuenta que muchas personas creen erróneamente que pasar una variable por referencia les dará un beneficio de rendimiento y, a menudo, esta fue la única razón para utilizar el paso por referencia del tiempo de llamada.De hecho, esto suele ser incorrecto, ya que el motor Zend que impulsa PHP utiliza una técnica llamada "copiar al escribir" para dejar múltiples variables que tienen el mismo valor apuntando al mismo fragmento de memoria, incluso si no están vinculadas como referencias.De hecho, la asignación de referencias generalmente derrotas esta optimización, debido a la forma en que el motor rastrea qué variables están en el estado de copia en escritura.