operators que - ¿Qué significan los operadores "=&" y "&=" en PHP?




lista than (3)

$a &= $b es la abreviatura de $a = $a & $b que es el operador bitwise-and .

$a =& $b asigna $ a como reference a $ b.

¿Qué significan los operadores "= &" / "& =" en PHP? ¿Dónde puedo leer información sobre ellos?

Buscar en Google no ayuda.


= &

$a =& $b convierte $a en un alias por $b . Si se cambia el valor o la referencia de $b , el valor o referencia de $b cambiará en consecuencia.

Esto difiere de "ambos apuntando al mismo lugar" cuando se trata de objetos: podría hacer $c = $d = new AnObject( ), y ambas variables apuntarían al mismo lugar; sin embargo, cambiar donde uno de los puntos no cambiará cuando el otro apunta. Es decir, $c = null no haría que $d = null . En el caso de $a =& $b , sin embargo, $a = null haría que $b = null .

Nota: Oficialmente, los alias se llaman realmente referencias. La terminología oficial es un poco incorrecta y ciertamente ambigua, por lo que opté por usar el término "alias". Para la documentación, vea php.net .

Usos y efectos

Con los valores escalares, =& es una especie de envoltura del valor en un objeto, por lo que puede cambiar el valor universalmente entre varias variables. Con tipos que normalmente se pasan por referencia (objetos), =& proporciona una referencia a una referencia.

Tiendo a usar =& cuando estoy trabajando con matrices asociativas. En lugar de volver a escribir $foo['bar']['foobar'] varias veces, puedo crear un alias: $foobar =& $foo['bar']['foobar'] . Estos incluso funcionan si el índice aún no existe. Si $foo['bar']['foobar'] no existe, entonces isset($foobar) será falso. Es mejor que usar una variable anterior simple, porque puedo crear el alias antes de probar la existencia de la clave sin desencadenar un error.

Solo asegúrese de desactivar ( unset($foobar) ) el alias cuando haya terminado. De lo contrario, si reutiliza el nombre de la variable más adelante, terminará sobrescribiendo a lo que apuntaba el alias.

También puede usar alias de otras formas; no están limitados a las asignaciones. Ellos trabajan con:

  • foreach loops: foreach ($a as &$b) Asignando a $b sobrescribirá el valor correspondiente en $a . ¡Desactiva $b cuando termines, o te encontrarás con problemas extraños!
  • Parámetros de función / método: function foobar(&$a) Asignando a $a dentro de foobar cambiará cualquier variable que el llamador haya pasado como $a .
  • valores de retorno de función / método: function &foobar() Lo que se devuelve puede ser modificado por la persona que llama; esto es útil para pasar alias. También es fácil abusar.
  • arrays: $a = array(&$b) Cualquier cambio a $a[0] ahora afectará a $b , incluidas las asignaciones.
  • call_user_func_array: call_user_func('foobar', array(&$a)) Suponiendo que foobar toma un solo parámetro de alias, foobar ahora puede modificar $a . Esto le permite llamar a funciones / métodos con parámetros de alias usando call_user_func_array .

Ejemplos

Escalares

$original = 1;
$copy = $original;
$reference =& $original;
// All three variables == 1.

$reference = 2;
// $original == 2, $reference == 2, $copy == 1

$original = 3;
// $original == 3, $reference == 3, $copy == 1

$copy = 4;
// $original == 3, $reference == 3, $copy == 4

Objetos

#!/usr/bin/env php
<?php
class Object
{
        private $properties;

        public function __construct(array $properties = array())
        {
                $this->properties = $properties;
        }

        public function __isset($key)
        {
                return isset($this->properties[$key]);
        }

        public function __unset($key)
        {
                unset($this->properties[$key]);
        }

        public function __get($key)
        {
                return isset($this->$key) ? $this->properties[$key] : null;
        }

        public function __set($key, $value)
        {
                $this->properties[$key] = $value;
        }

        public function __toString()
        {
                return print_r($this->properties, true);
        }
}

function print_vars()
{
        global $original, $ref, $refref;

        echo
                '$original: ', $original,
                '$ref: ', $ref,
                '$refref: ', $refref,
                PHP_EOL;
}

$original = new Object(array('a' => 1, 'b' => 2, 'c' => 3));
$ref = $original;
$refref =& $original;
print_vars();
/*
$original: Array
(
    [a] => 1
    [b] => 2
    [c] => 3
)
$ref: Array
(
    [a] => 1
    [b] => 2
    [c] => 3
)
$refref: Array
(
    [a] => 1
    [b] => 2
    [c] => 3
)
*/

$original->a = 'duck';
$ref->b = 'moose';
$refref->c = 'cow';
print_vars();
/*
$original: Array
(
    [a] => duck
    [b] => moose
    [c] => cow
)
$ref: Array
(
    [a] => duck
    [b] => moose
    [c] => cow
)
$refref: Array
(
    [a] => duck
    [b] => moose
    [c] => cow
)
*/

// This carries over to $refref, but not $ref.
$original = new Object(array('x' => 1, 'y' => 2, 'z' => 3));
print_vars();
/*
$original: Array
(
    [x] => 1
    [y] => 2
    [z] => 3
)
$ref: Array
(
    [a] => duck
    [b] => moose
    [c] => cow
)
$refref: Array
(
    [x] => 1
    [y] => 2
    [z] => 3
)
 */

// This does *not* carry over to $original or $ref.
$ref = new Object(array('o' => 42, 'm' => 123, 'n' => 1337));
print_vars();
/*
$original: Array
(
    [x] => 1
    [y] => 2
    [z] => 3
)
$ref: Array
(
    [o] => 42
    [m] => 123
    [n] => 1337
)
$refref: Array
(
    [x] => 1
    [y] => 2
    [z] => 3
)
*/

// This *does* carry over to $original, but not $ref.
$refref = new Object(array('alpha' => 10, 'beta' => 20, 'gamma' => 30));
print_vars();
/*
$original: Array
(
    [alpha] => 10
    [beta] => 20
    [gamma] => 30
)
$ref: Array
(
    [o] => 42
    [m] => 123
    [n] => 1337
)
$refref: Array
(
    [alpha] => 10
    [beta] => 20
    [gamma] => 30
)
*/
?>

& =

&= no está relacionado con =& . Viene de un conjunto de operaciones de asignación. Aquí hay solo algunos:

  • +=
  • -=
  • *=
  • /=

Mira la tendencia aquí?

Los operadores aritméticos binarios generalmente tienen contrapartidas de asignación. Digamos que @ era un operador aritmético (no es a partir de la escritura), de modo que $a @ $b generalmente arroja un número cuando $a y $b son números. (Piense: suma, multiplicación, división, etc.) ¿Con qué frecuencia necesita hacer algo como esto?

$a = $a @ $b;

Muy a menudo. ¿No parece un poco innecesario repetir $a ? Muchos idiomas, incluido PHP, resuelven esto con una serie de operadores de asignación:

$a @= $b;

Mucho más simple, y para un programador acostumbrado a esta notación, quizás más conciso y descriptivo a simple vista. (Ciertamente me resulta más fácil de leer, ya que estoy tan acostumbrado.) Así que para duplicar una variable:

$a *= 2;

Rápido, fácil y relativamente descriptivo. Algunos lenguajes, incluido PHP, extienden esta función más allá de la aritmética para una o dos operaciones adicionales. Notablemente:

$a = $a . 'Appended text';
// Is the same as:
$a .= 'Appended text';

Muy útil.

&= cae entre estos operadores de asignación, porque & representa una operación aritmética Y a nivel de bit . Hay algunos otros enumerados en la documentación de PHP (ver el enlace mencionado anteriormente), todos los cuales son comunes a muchos lenguajes de programación.

Esto significa que $a &= $b es lo mismo que $a = $a & $b .


??! es un trigraph que se traduce a | . Eso dice:

!ErrorHasOccured() || HandleError();

el cual, por cortocircuito, es equivalente a:

if (ErrorHasOccured())
    HandleError();

Gurú de la semana (trata con C ++ pero relevante aquí), donde recogí esto.

Posible origen de trigraphs o como @DwB señala en los comentarios, es más probable que EBCDIC sea difícil (otra vez). This discusión en el tablero de IBM developerworks parece apoyar esa teoría.

De ISO / CEI 9899: 1999 §5.2.1.1, nota 12 (h / t @ Random832):

Las secuencias de trigraph permiten la entrada de caracteres que no están definidos en el Conjunto de códigos invariantes como se describe en ISO / IEC 646, que es un subconjunto del conjunto de códigos ASCII de EE. UU. De siete bits.





php operators