2011-05-26 34 views
10

El siguiente patrón solía ser posible en PHP:arrays PHP y pasar por referencia

function foo($arr) 
{ 
    // modify $arr in some way 
    return $arr; 
} 

Esto entonces se podría llamar usando el paso por valor:

$arr = array(1, 2, 3); 
$newarr = foo($arr); 

o de Transmisión por referencia:

$arr = array(1, 2, 3); 
foo(&$arr); 

pero "el tiempo de referencia de la llamada por referencia ha quedado en desuso". La modificación de la firma de la función:

function foo(&$arr) 

manejará el caso pase por referencia, pero se romperá la naturaleza de doble propósito de la función original, ya que el paso por el valor ya no es posible.

¿Hay alguna forma de evitar esto?

+0

Activa E_DEPRECATED, que es solo un * nivel de error *. Pero la función en sí misma no se ve afectada. No es "ya no es posible". (Y aún no va a ser eliminado en los próximos años PHP 5.4 ..) – mario

+0

Quise decir que pasar por valor cuando se llama a una función que está declarada como tomar su argumento por referencia no es posible. Como usted señala, todavía es * posible * pasar por referencia, incluso si la función no declara su argumento de esa manera, pero siempre me gusta pensar que las cosas obsoletas deben evitarse si es posible. –

+1

Sí, eso es exactamente por lo que * declaró * obsoleto. Comúnmente se mal uso sin pensarlo mucho. Y este mensaje de error está destinado a asustar a la gente de esa sintaxis. Ahora que ya pensaste en tu código actual, ya no se aplica a ti. (Evitaría las soluciones falsas sobre la sintaxis soportada no-any-soon-to-be-removed.) – mario

Respuesta

5

creo que esto es lo más cerca que se obtiene:

function foo(&$bar) { ... } 

foo($array);    // call by reference 
$bar = foo($_tmp = $array); // call by value 

Por desgracia, requerirán algunos cambios en cada llamada.

+0

Esa es probablemente la mejor alternativa aquí; explícito y legible – mario

+1

Debo señalar que realmente no recomendaría escribir código de esa manera. por ejemplo, simplemente podría escribir '$ bar = $ array; foo ($ bar); 'El objetivo aquí era simplemente intentar imitar la sintaxis en desuso lo más cerca posible. Además, si va a cambiar su código, tenga en cuenta que las líneas que usan pass-by-value no generarán ninguna advertencia, y al cambiar la función de esta forma, se cambiará silenciosamente el comportamiento en esos casos. Así que, personalmente, seguiría usando el código tal como está, y mientras tanto buscaría mejores bibliotecas de terceros. – Matthew

2

La naturaleza de doble propósito era estúpida, por lo que el comportamiento ha quedado obsoleto. Modifique la firma de la función, como sugiere.

+7

La naturaleza de doble propósito no era estúpida, era peligroso porque podía modificar una variable si la pasaba por referencia. Ahora estamos obligados a declarar explícitamente si la variable se pasa por referencia o no. Tiene sus ventajas (los programadores menos cuidadosos no se dispararán en su propia pierna y PHP finalmente puede pasar argumentos sin copiar los valores) y los inconvenientes (sin función doble, por lo que la función que hace casi lo mismo tiene que declararse dos veces). –

+0

@Bobby: Lo que dijo @Michael. :) –

+0

Excelente resumen, @Michael –

1

Lamentablemente, no creo que haya una forma de evitarlo.

Simplemente haga que su función use la referencia con &.

1

Una solución sencilla consiste en preparar una función de contenedor:

function foo($arr) { 
    return foo_ref($arr); 
} 

function foo_ref(&$arr) { 
    ... 

A continuación, dependiendo del uso actual, o bien invocar la normalidad o la foo()foo_ref() si desea que la matriz para ser modificado en su lugar.


También hay un parámetro array(&$wrap) trampa común, pero eso no parece adecuado en su caso. Una solución más contemporánea sería este engañoso truco:

// pass by value 
foo($array); 

// pass by reference (implicitly due to being an object) 
foo($array = new ArrayObject($array)); 

Esto permite pasar una referencia similar a las funciones no preparadas. Personalmente, preferiría mantener la advertencia E_DEPRECATED y la sintaxis prevista para este fin.

+2

Lamentablemente, 'ArrayObject' no se puede usar con funciones de matriz, por lo que no es necesariamente un" arreglo "directo. De lo contrario, probablemente funcionaría. – Matthew

Cuestiones relacionadas