A razão pela qual diferentes artigos parecem dizer coisas diferentes é que estão falando sobre diferentes tipos de passagem por referência.
A principal coisa que determina se um parâmetro deve ser passado por referência é a própria assinatura da função, e os fundamentos disso não mudaram desde o PHP 4.Considere este exemplo:
function foo( $by_value, &$by_reference ) { /* ... */ }
$a = 1; $b = 2;
foo( $a, $b );
Aqui, a variável externa $a
está sendo passado para a função por valor, como se estivesse sendo atribuído como $by_value = $a;
- muda para $by_value
não pode afetar $a
.A variável $b
porém está sendo passado por referência;assim como uma atribuição do formulário $by_reference =& $b;
isso significa que há uma variável referenciada por dois nomes e qualquer atribuição a uma delas atuará como uma atribuição a ambos.
Se você passar um valor "comum" (uma string, um número ou um array) por valor, seu valor será apenas copiado para a nova variável. A partir do PHP 5:Se você passar um objeto por valor, entretanto, algo um pouco diferente acontece - o "valor" copiado é apenas um ponteiro para o mesmo objeto.Isto significa que se $a
fosse um objeto, você poderia chamar $by_value->some_property = 42;
e $a->some_property
também seria 42
.No entanto, se você atribuiu algum novo valor a $by_value
, ainda assim não afetaria $a
.
Até PHP 5.4, houve um extra forma de passar um parâmetro por referência, que era "forçar" o comportamento da referência na hora da chamada.Isso significava que você poderia escrever foo(&$a, &$b);
e "capturar" alterações feitas em $by_value
dentro de foo()
função.Depender disso geralmente era uma má ideia e por isso foi removido.(Ele chegou ao 5.4 porque era planejado para ser removido no PHP 6, mas esse projeto foi colocado em espera por tempo indeterminado, com as mudanças menores chegando ao 5.3 e 5.4).
Finalmente, as funções podem retornar uma variável por referência (como discutido no manual aqui).Isso é um pouco complicado, pois na verdade exige que você coloque &
em dois lugares:no início da declaração da função, para dizer que return
deve significar "retornar esta referência de variável" e não "retornar este valor";e no código que a chama, atribuir uma variável a essa referência, em vez de apenas copiar seu valor.Aqui está um exemplo bobo que combina um parâmetro de referência com um retorno de referência (os dois não precisam andar juntos, é apenas um exemplo):
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
Observe que muitas pessoas acreditam erroneamente que passar uma variável por referência lhes proporcionará um benefício de desempenho, e essa geralmente era a única razão para usar a passagem por referência no tempo de chamada.Na verdade, isso geralmente está errado, já que o Zend Engine que alimenta o PHP usa uma técnica chamada "copy on write" para deixar múltiplas variáveis que têm o mesmo valor apontando para o mesmo pedaço de memória, mesmo que não estejam ligadas como referências.Na verdade, a atribuição de referência geralmente derrotas esta otimização, devido à forma como o mecanismo rastreia quais variáveis estão no estado copy-on-write.