¿Las variables PHP se pasan por valor o por referencia?
¿Las variables PHP se pasan por valor o por referencia?
Respuestas:
Es por valor de acuerdo con la documentación de PHP .
Por defecto, los argumentos de la función se pasan por valor (de modo que si se cambia el valor del argumento dentro de la función, no se cambia fuera de la función). Para permitir que una función modifique sus argumentos, se deben pasar por referencia.
Para tener un argumento para una función siempre pasado por referencia, anteponga un signo de y comercial ( & ) al nombre del argumento en la definición de la función.
<?php
function add_some_extra(&$string)
{
$string .= 'and something extra.';
}
$str = 'This is a string, ';
add_some_extra($str);
echo $str; // outputs 'This is a string, and something extra.'
?>
$str = add_some_extra($str);
si no estuviera usando la referencia, ¿verdad? entonces, ¿cuál es el verdadero valor agregado de eso?
$str
lo que se asignaría nulo, en su caso.
En PHP, por defecto, los objetos se pasan como copia de referencia a un nuevo objeto.
Ver este ejemplo .............
class X {
var $abc = 10;
}
class Y {
var $abc = 20;
function changeValue($obj)
{
$obj->abc = 30;
}
}
$x = new X();
$y = new Y();
echo $x->abc; //outputs 10
$y->changeValue($x);
echo $x->abc; //outputs 30
Ahora mira esto ..............
class X {
var $abc = 10;
}
class Y {
var $abc = 20;
function changeValue($obj)
{
$obj = new Y();
}
}
$x = new X();
$y = new Y();
echo $x->abc; //outputs 10
$y->changeValue($x);
echo $x->abc; //outputs 10 not 20 same as java does.
Ahora mira esto ..............
class X {
var $abc = 10;
}
class Y {
var $abc = 20;
function changeValue(&$obj)
{
$obj = new Y();
}
}
$x = new X();
$y = new Y();
echo $x->abc; //outputs 10
$y->changeValue($x);
echo $x->abc; //outputs 20 not possible in java.
Espero que puedas entender esto.
$y
no es necesario, no hay nada function changeValue
que requiera que esté adentro class Y
, de modo que se enreden dos conceptos no relacionados. Me mudaría function changeValue
al alcance exterior, justo arriba $x = new X();
. Eliminar todas las referencias a $y
. Ahora es más fácil ver que los dos primeros ejemplos dejan solo $ x, y el tercero cambia su contenido a new Y()
. Lo que sería más fácil para ver si se vació el type
de $x
- el hecho de que tanto X
y Y
pasan a incluir un $abc
campo también es irrelevante para lo que se demuestra
Parece que mucha gente se confunde por la forma en que se pasan los objetos a las funciones y por lo que pasa por referencia. Las variables de objeto todavía se pasan por valor, es solo el valor que se pasa en PHP5 es un identificador de referencia. Como prueba:
<?php
class Holder {
private $value;
public function __construct($value) {
$this->value = $value;
}
public function getValue() {
return $this->value;
}
}
function swap($x, $y) {
$tmp = $x;
$x = $y;
$y = $tmp;
}
$a = new Holder('a');
$b = new Holder('b');
swap($a, $b);
echo $a->getValue() . ", " . $b->getValue() . "\n";
Salidas:
a, b
Para el paso por referencia significa que podemos modificar las variables que son vistos por la persona que llama. Lo que claramente no hace el código anterior. Necesitamos cambiar la función de intercambio a:
<?php
function swap(&$x, &$y) {
$tmp = $x;
$x = $y;
$y = $tmp;
}
$a = new Holder('a');
$b = new Holder('b');
swap($a, $b);
echo $a->getValue() . ", " . $b->getValue() . "\n";
Salidas:
b, a
para pasar por referencia.
swap
función; en otras palabras, si los objetos fueron "pasados por valor". Por otro lado, también es exactamente lo que esperaría si se pasara un identificador de objeto a la función, que en realidad es lo que sucede. Su código no distingue entre estos dos casos.
http://www.php.net/manual/en/migration5.oop.php
En PHP 5 hay un nuevo modelo de objetos. El manejo de objetos de PHP se ha reescrito por completo, lo que permite un mejor rendimiento y más funciones. En versiones anteriores de PHP, los objetos se manejaban como tipos primitivos (por ejemplo, enteros y cadenas). El inconveniente de este método fue que semánticamente todo el objeto se copió cuando se asignó una variable o se pasó como parámetro a un método. En el nuevo enfoque, se hace referencia a los objetos por identificador y no por valor (se puede pensar en un identificador como el identificador de un objeto).
Las variables PHP se asignan por valor, se pasan a funciones por valor, y cuando contienen / representan objetos se pasan por referencia. Puede forzar que las variables pasen por referencia usando un &
Asignado por valor / ejemplo de referencia:
$var1 = "test";
$var2 = $var1;
$var2 = "new test";
$var3 = &$var2;
$var3 = "final test";
print ("var1: $var1, var2: $var2, var3: $var3);
saldría
var1: prueba, var2: prueba final, var3: prueba final
Aprobado por valor / referencia examen:
$var1 = "foo";
$var2 = "bar";
changeThem($var1, $var2);
print "var1: $var1, var2: $var2";
function changeThem($var1, &$var2){
$var1 = "FOO";
$var2 = "BAR";
}
daría salida:
var1: foo, var2 BAR
Variables de objeto pasadas por examen de referencia:
class Foo{
public $var1;
function __construct(){
$this->var1 = "foo";
}
public function printFoo(){
print $this->var1;
}
}
$foo = new Foo();
changeFoo($foo);
$foo->printFoo();
function changeFoo($foo){
$foo->var1 = "FOO";
}
Daría salida:
FOO
(ese último ejemplo podría ser mejor probablemente ...)
$foo
es un puntero a un objeto . $foo
se pasa por valor a la función changeFoo()
, ya changeFoo()
que no declaró su parámetro con a &
.
Puede pasar una variable a una función por referencia. Esta función podrá modificar la variable original.
Puede definir el pasaje por referencia en la definición de la función:
<?php
function changeValue(&$var)
{
$var++;
}
$result=5;
changeValue($result);
echo $result; // $result is 6 here
?>
Puedes hacerlo de cualquier manera.
ponga un símbolo '&' al frente y la variable que está pasando se convierte en una y la misma que su origen. es decir: puede pasar por referencia, en lugar de hacer una copia de la misma.
entonces
$fred = 5;
$larry = & $fred;
$larry = 8;
echo $fred;//this will output 8, as larry and fred are now the same reference.
Las variables que contienen tipos primitivos se pasan por valor en PHP5. Las variables que contienen objetos se pasan por referencia. Hay un artículo bastante interesante de Linux Journal de 2006 que menciona esta y otras diferencias OO entre 4 y 5.
&
.
Los objetos se pasan por referencia en PHP 5 y por valor en PHP 4. ¡Las variables se pasan por valor por defecto!
Lea aquí: http://www.webeks.net/programming/php/ampersand-operator-used-for-assigning-reference.html
&
.
&
delante de los parámetros en la definición; si se pasaran por valor, el objeto contenido en el ámbito que llamaba a la función como parámetro lo haría No ser afectado.
class Holder
{
private $value;
public function __construct( $value )
{
$this->value = $value;
}
public function getValue()
{
return $this->value;
}
public function setValue( $value )
{
return $this->value = $value;
}
}
class Swap
{
public function SwapObjects( Holder $x, Holder $y )
{
$tmp = $x;
$x = $y;
$y = $tmp;
}
public function SwapValues( Holder $x, Holder $y )
{
$tmp = $x->getValue();
$x->setValue($y->getValue());
$y->setValue($tmp);
}
}
$a1 = new Holder('a');
$b1 = new Holder('b');
$a2 = new Holder('a');
$b2 = new Holder('b');
Swap::SwapValues($a1, $b1);
Swap::SwapObjects($a2, $b2);
echo 'SwapValues: ' . $a2->getValue() . ", " . $b2->getValue() . "<br>";
echo 'SwapObjects: ' . $a1->getValue() . ", " . $b1->getValue() . "<br>";
Los atributos siguen siendo modificables cuando no se pasan por referencia, así que tenga cuidado.
Salida:
SwapObjects: b, a SwapValues: a, b
Para cualquiera que se encuentre con esto en el futuro, quiero compartir esta joya de los documentos PHP, publicados por un usuario anónimo :
Parece que hay algo de confusión aquí. La distinción entre punteros y referencias no es particularmente útil. El comportamiento en algunos de los ejemplos "completos" ya publicados puede explicarse en términos unificadores más simples. El código de Hayley, por ejemplo, está haciendo EXACTAMENTE lo que debe esperar. (Usando> = 5.3)
Primer principio: un puntero almacena una dirección de memoria para acceder a un objeto. Cada vez que se asigna un objeto, se genera un puntero. (Todavía no he profundizado demasiado en el motor Zend, pero por lo que puedo ver, esto se aplica)
Segundo principio y fuente de la mayor confusión: el paso de una variable a una función se realiza de forma predeterminada como un paso de valor, es decir, está trabajando con una copia. "¡Pero los objetos se pasan por referencia!" Un error común tanto aquí como en el mundo de Java. Nunca dije una copia de lo que. El paso predeterminado se realiza por valor. Siempre. Lo que se copia y se pasa, sin embargo, es el puntero. Cuando utilice "->", por supuesto accederá a los mismos elementos internos que la variable original en la función de llamada. Simplemente usando "=" solo jugará con copias.
3er principio: "&" establece automática y permanentemente otro nombre / puntero de variable en la misma dirección de memoria que otra cosa hasta que los desacople. Es correcto usar el término "alias" aquí. Piense en ello como unir dos punteros en la cadera hasta que se separen por la fuerza con "unset ()". Esta funcionalidad existe tanto en el mismo ámbito como cuando se pasa un argumento a una función. A menudo, el argumento pasado se denomina "referencia", debido a ciertas distinciones entre "pasar por valor" y "pasar por referencia" que eran más claras en C y C ++.
Solo recuerde: los punteros a los objetos, no los objetos en sí, se pasan a las funciones. Estos punteros son COPIAS del original a menos que use "&" en su lista de parámetros para pasar los originales. Solo cuando profundice en el interior de un objeto, los originales cambiarán.
Y aquí está el ejemplo que brindan:
<?php
//The two are meant to be the same
$a = "Clark Kent"; //a==Clark Kent
$b = &$a; //The two will now share the same fate.
$b="Superman"; // $a=="Superman" too.
echo $a;
echo $a="Clark Kent"; // $b=="Clark Kent" too.
unset($b); // $b divorced from $a
$b="Bizarro";
echo $a; // $a=="Clark Kent" still, since $b is a free agent pointer now.
//The two are NOT meant to be the same.
$c="King";
$d="Pretender to the Throne";
echo $c."\n"; // $c=="King"
echo $d."\n"; // $d=="Pretender to the Throne"
swapByValue($c, $d);
echo $c."\n"; // $c=="King"
echo $d."\n"; // $d=="Pretender to the Throne"
swapByRef($c, $d);
echo $c."\n"; // $c=="Pretender to the Throne"
echo $d."\n"; // $d=="King"
function swapByValue($x, $y){
$temp=$x;
$x=$y;
$y=$temp;
//All this beautiful work will disappear
//because it was done on COPIES of pointers.
//The originals pointers still point as they did.
}
function swapByRef(&$x, &$y){
$temp=$x;
$x=$y;
$y=$temp;
//Note the parameter list: now we switched 'em REAL good.
}
?>
Escribí una publicación de blog extensa y detallada sobre este tema para JavaScript , pero creo que se aplica igualmente bien a PHP, C ++ y cualquier otro lenguaje donde la gente parece estar confundida acerca de pasar por valor frente a pasar por referencia.
Claramente, PHP, como C ++, es un lenguaje que admite paso por referencia. Por defecto, los objetos se pasan por valor. Cuando se trabaja con variables que almacenan objetos, ayuda ver esas variables como punteros (porque eso es fundamentalmente lo que son, a nivel de ensamblaje). Si pasa un puntero por valor, aún puede "rastrear" el puntero y modificar las propiedades del objeto al que apunta. Lo que no puede hacer es que apunte a un objeto diferente. Solo si declara explícitamente que un parámetro se pasa por referencia podrá hacerlo.
En realidad, ambos métodos son válidos, pero depende de sus requisitos. Los valores de referencia por referencia a menudo hacen que su secuencia de comandos sea lenta. Por lo tanto, es mejor pasar las variables por valor considerando el tiempo de ejecución. Además, el flujo de código es más consistente cuando pasa variables por valor.
Use esto para funciones cuando desee simplemente alterar la variable original y devolverla nuevamente al mismo nombre de variable con su nuevo valor asignado.
function add(&$var){ // The & is before the argument $var
$var++;
}
$a = 1;
$b = 10;
add($a);
echo "a is $a,";
add($b);
echo " a is $a, and b is $b"; // Note: $a and $b are NOT referenced
Depende de la versión, 4 es por valor, 5 es por referencia.