PHP入門 代入演算子

左辺で指定した変数に対して右辺の値をセット(代入)するための演算子を解説しています。また、代入演算子には、代数演算子やビット演算子などを合わせた機能を提供する複合代入演算子も含まれます。

主な代入演算子

演算子概要用例
=変数などに値を代入$x = 10;
+=左辺と右辺を加算した結果を、左辺に代入$x = 5; $x+=2; 結果は7
-=左辺と右辺を減算した結果を、左辺に代入$x = 5; $x-=2; 結果は3
*=左辺と右辺を乗算した結果を、左辺に代入$x = 5; $x*=2; 結果は10
**=左辺と右辺を累乗した結果を、左辺に代入$x = 5; $x**=2; 結果は25
/=左辺と右辺を除算した結果を、左辺に代入$x = 5; $x/=2; 結果は2.5
%=左辺と右辺を除算した余りを、左辺に代入$x = 5; $x%=2; 結果は1
.=左辺と右辺を連結した文字列を、左辺に代入$x = ‘Foo’; $x.=’Bar’; 結果はFooBar
??=左辺が非nullならその値を、nullなら右辺の値を代入$x = 10; $x??=1; 結果は10
&=左辺と右辺をビット論理積した結果を、左辺に代入$x = 10; $x&=1; 結果は0
|=左辺と右辺をビット論理和した結果を、左辺に代入$x = 10; $x|=1; 結果は11
^=左辺と右辺をビット排他論理和した結果を、左辺に代入$x = 10; $x^=1; 結果は11
<<=左辺と右辺の値だけ左シフトした結果を、左辺に代入$x = 10; $x<<=1; 結果は20
>>=左辺と右辺の値だけ右シフトした結果を、左辺に代入$x = 10; $x>>=1; 結果は5

複合代入演算子は、「左辺と右辺の値を演算した結果を左辺に代入する」ための演算子です。つまり、次のコードは意味的に等価です。

※x=複合演算子として使用できる代数/ビット/文字列演算子を表します。

$i x= $j  左右は等価です  $i = $i x $j;

値による代入と参照による代入

変数とは、値の格納先(アドレス)に対して付けられた名札となっています。「=」演算子で変数を変数に代入する場合は、値による代入が基本となり、メモリ上の値を別のアドレスにコピーすることを言います。値による代入は、代入した変数と代入された変数は別物なので、元の変数の値が変更されても代入された側の変数が影響を受けることはありません。

これに対して、参照(リファレンス)による代入は、メモリ上のアドレスそのものを引き渡す代入のことを言います。参照による代入では、元の変数に対して加えた変更は代入された側の変数にも及ぶということになります。

参照による代入を行うには、「=」演算子の後方に参照を表す「&」演算子を指定します。

<?php
$x = 1;
$y = &$x;   //$xのアドレスを$yにコピー
$x = 5;     //$xの値を変更
print $y;   //結果:5($yも影響を受ける)
オブジェクト型だけは例外で、参照に代入が基本です。オブジェクトを明示的にコピーするには、clone命令を使用します。

分割代入

分割代入とは、配列/連想配列などを分解し、配下の要素を個々の変数に代入するための構文です。左辺に要素の数だけ変数を列挙し、全体をブラケット([…])でくくります。左辺の要素数は右辺(配列)のそれいと等しいか、少なくなければなりません。

<?php
$data = [1, 2, 3, 4, 5];
[$a, $b, $c, $d, $e] = $data;
print $a;  //結果:1
print $b;  //結果:2
print $c;  //結果:3
print $d;  //結果:4
print $e;  //結果:5

左辺の要素数が右辺よりも大きい場合は、不足分は無視されます。

$data = [1, 2, 3, 4, 5];
[$a, $b, $c] = $data;

ブラケットによる配列分割は、list関数でも代用できます。

ブラケット構文はPHP7.1から導入された分割の仕組みです。
list($a, $b, $c, $d, $e) = $data;

一部の要素を切り捨てる

分割代入で途中の要素を無視するならば、ブラケット内部でスキップする数だけカンマを列挙してください。以下の例では、0、2番目の要素がスキップされます。

<?php
$data = [1, 2, 3, 4, 5];
[  , $a,  , $b, $c] = $data;
print $a;  //結果:2
print $b;  //結果:4
print $c;  //結果:5

複数の要素を連続してスキップする場合、位置関係がわかりにくいケースがあるので、そのような場合は、ダミーの変数として「$_」を置きます。

[$_, $a, $_, $b, $c] = $data;

一部の要素だけを取得する

「インデックス値 => 変数」の形式で、特定の要素だけを分割代入することも可能です。代入元の配列に対して、取り出す要素が少ない場合には、こちらの用法を利用します。

<?php
$data = [1, 2, 3, 4, 5];
[1 => $a, 4 => $b] = $data;
print $a;   //結果:2
print $b;   //結果:5

この記法を利用することで、連想配列から個々の要素を取り出すことも可能です。

<?php
$map = ['title' => 'サンプル', 'price' => 3000];
['title' => $title, 'price' => $price] = $map;
print $title;   //結果:サンプル
print $price;   //結果:3000

入れ子の配列を分割する

入れ子の配列を分解することもできます。

<?php
$data = [1, 2, [31, 32, 33]];  //➊
[$a, $b ,$c] = $data;
print_r($a);   //結果:1
print_r($b);   //結果:2
print_r($c);   //結果:Array ([0] => 31 [1] => 32 [2] => 33)

[$x, $y ,[$z1, $z2, $z3]] = $data;//➋
print_r($x);   //結果:1
print_r($y);   //結果:2
print_r($z1);  //結果:31
print_r($z2);  //結果:32
print_r($z3);  //結果:33

➊のように、単に変数を列挙した場合は、対応する変数(ここでは$c)に入れ子の配列がそのまま代入されます。入れ子の配列も展開したいならば、➋のように代入先(左辺)もブラケット([…])を入れ子にしてください。

入れ子の連想配列も処理できます。

['author' => ['name' => $anme,'address' => $address]] = $book;

変数のスワッピング

分割代入を利用することで、変数の値を入れ替えること(スワッピング)もできます。もしも分割代入を利用しないのであれば、いずれかの変数を一旦別の変数に退避させる必要があります

<?php
$X = 15;
$y = 38;
[$y, $x] = [$x, $y];
print $x;   //結果:38
print $y;   //結果:15