Что делать "= &" / "& =" в PHP? Где я могу прочитать информацию о них?
Поиск Google не помогает.
Что делать "= &" / "& =" в PHP? Где я могу прочитать информацию о них?
Поиск Google не помогает.
$a &= $b
сокращен для $a = $a & $b
, который является оператором побитовым и.
$a =& $b
присваивает $a как reference до $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)
будет ложным. Это лучше, чем использование простой старой переменной, потому что я могу создать псевдоним перед тестированием на наличие ключа без возникновения ошибки.
Не забудьте отменить (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
)
*/
?>
&=
не имеет отношения к =&
. Он исходит из набора операций присваивания. Вот только несколько:
+=
-=
*=
/=
См. здесь тренд?
Двоичные арифметические операторы обычно имеют сопоставления с назначением. Скажем, @
были арифметическим оператором (это не так, как написано), так что $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
.