Что означают операторы «= &» / «& =» в PHP? Где я могу прочитать информацию о них?
Поиск Google не помогает.
$a &= $b
является коротким для $a = $a & $b
который является побитовым и оператором.
$a =& $b
присваивает $ a как ссылку на $ b.
$a =& $b
превращает $a
в псевдоним для $b
. Если значение или ссылка $a
изменяется, значение или ссылка в $b
будут соответственно изменяться.
Это отличается от того, что «оба указывают на одно и то же место», когда дело доходит до объектов: я мог бы сделать $c = $d = new AnObject(
), и обе переменные указывали бы на одно и то же место; однако, изменение, где одно очко не изменилось бы там, где другие точки. То есть $c = null
не сделает $d = null
. В случае $a =& $b
, однако, $a = null
сделает $b = null
.
Примечание. Официально псевдонимы на самом деле называются ссылками. Официальная терминология немного ошибочна и, безусловно, неоднозначна, поэтому я решил использовать термин «псевдоним» вместо этого. Документацию см. В php.net .
Со скалярными значениями =&
является своего рода переносом значения в объект, так что вы можете изменить значение универсально среди нескольких переменных. С типами, которые обычно передаются по ссылке (объекты), =&
предоставляет ссылку на ссылку.
Я обычно использую =&
когда я работаю с ассоциативными массивами. Несколько раз, переписывая $foo['bar']['foobar']
, я могу создать псевдоним: $foobar =& $foo['bar']['foobar']
. Они даже работают, если индекс еще не существует. Если $foo['bar']['foobar']
не существует, то isset($foobar)
будет false. Это лучше, чем использование простой старой переменной, потому что я могу создать псевдоним перед тестированием на наличие ключа без возникновения ошибки.
Просто обязательно отмените ( unset($foobar)
) псевдоним, когда вы закончите. В противном случае, если вы повторно используете имя переменной позже, вы в конечном итоге перепишете все, что указывал псевдоним.
Вы также можете использовать псевдонимы другими способами – они не ограничены назначениями. Они работают с:
foreach ($a as &$b)
Присвоение $b
будет перезаписывать соответствующее значение в $a
. Unset $b
когда вы закончите, или у вас возникнут странные проблемы! function foobar(&$a)
Присвоение переменной $a
внутри foobar
изменяет любую переменную, передаваемую вызывающим пользователем как $a
. function &foobar()
Все, что возвращается, может быть изменено вызывающим; это полезно для обхода псевдонимов. Это также легко злоупотреблять. $a = array(&$b)
Любые изменения в $a[0]
теперь будут влиять на $b
, включая присвоения. call_user_func('foobar', array(&$a))
Предполагая, что foobar
принимает один параметр псевдонима, foobar
теперь может изменять $a
. Это позволяет вам вызывать функции / методы с параметрами псевдонима, используя call_user_func_array
. $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
#!/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 ) */ ?>
не#!/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 ) */ ?>
&=
имеет отношения к =&
. Он исходит из набора операций присваивания. Вот лишь несколько:
+=
-=
*=
/=
См. Тренд здесь?
Двоичные арифметические операторы, как правило, имеют сопоставления. Предположим, что @
был арифметическим оператором (это не так), что $a @ $b
обычно дает число, когда $a
и $b
являются числами. (Подумайте: добавление, умножение, деление и т. Д.). Как часто вам нужно делать что-то подобное?
$a = $a @ $b;
Довольно часто. Не кажется ли вам лишним повторять $a
? Многие языки, включая PHP, решают это с помощью массива операторов присваивания:
$a @= $b;
Гораздо проще, и программисту, привыкшему к этим обозначениям, возможно, более кратким и описательным с первого взгляда. (Мне, конечно, легче читать, поскольку я так привык). Чтобы удвоить переменную:
$a *= 2;
Быстро, легко и относительно описательно. Некоторые языки, включая PHP, расширяют эту функцию за пределами арифметики для дополнительной операции или двух. В частности:
$a = $a . 'Appended text'; // Is the same as: $a .= 'Appended text';
Очень полезно.
&=
падает среди этих операторов присваивания, поскольку &
представляет побитовую арифметическую операцию И. Есть несколько других, перечисленных в документации PHP (см. Вышеупомянутую ссылку), которые являются общими для многих языков программирования.
Это означает, что $a &= $b
совпадает с $a = $a & $b
.