web-dev-qa-db-ja.com

PHP=の「=」および「&=」演算子はどういう意味ですか?

PHP=の "="/"&="演算子はどういう意味ですか?それらに関する情報はどこで読むことができますか?

Googleを検索しても役に立ちません。

66
heyheyhey

$a &= $b$a = $a & $bの短縮形であり、これは bitwise-and 演算子です。

$a =& $bは、$ aを reference として$ bに割り当てます。

90
moo

_$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ループ:foreach ($a as &$b) _$b_に割り当てると、_$a_の対応する値が上書きされます。完了したら_$b_の設定を解除します。そうしないと、奇妙な問題が発生します。
  • 関数/メソッドパラメータ:function foobar(&$a)foobar内の_$a_への割り当ては、呼び出し元が_$a_として渡した変数を変更します。
  • 関数/メソッドの戻り値:function &foobar()返されるものはすべて、呼び出し元が変更できます。これはエイリアスを渡すのに便利です。悪用も簡単です。
  • 配列:$a = array(&$b) _$a[0]_への変更は、割り当てを含め、_$b_に影響します。
  • call_user_func_array: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
)
*/
?>
_

&=

_&=_は_=&_とは関係ありません。これは、一連の割り当て操作から取得されます。ここにいくつかあります:

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

ここでトレンドを見ますか?

2項算術演算子には通常、対応する代入演算子があります。 _@_が_$a @ $b_と_$a_が数値の場合、一般に_$b_は数値を生成する算術演算子(これは執筆時点ではありません)であるとしましょう。 (考えてください:加算、乗算、除算など)このようなことをする必要がある頻度はどれくらいですか?

_$a = $a @ $b;
_

かなり頻繁に。 _$a_を繰り返す必要はないでしょうか? PHPを含む多くの言語は、代入演算子の配列でこれを解決します。

_$a @= $b;
_

はるかに単純で、この表記に慣れているプログラマにとっては、おそらく一目でより簡潔で説明的になります。 (慣れているので、確かに読みやすくなります。)変数を2倍にするには:

_$a *= 2;
_

すばやく、簡単で、比較的わかりやすい。 PHPを含む一部の言語では、この機能を算術を超えて拡張し、追加の1〜2回の操作を行います。特に:

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

非常に便利。

_&=_は ビットごとの算術AND演算 を表すため、_&_はこれらの代入演算子に含まれます。 PHPのドキュメント(前述のリンクを参照))には他にもいくつかリストされていますが、それらはすべて多くのプログラミング言語に共通です。

つまり、_$a &= $b_は_$a = $a & $b_と同じです。

36
Zenexer