PHPの代入演算子は式なので値が返ってきます。
どういうことかというと、$a = 10
という代入式を書くと$a
に10が代入されますが、それとは別に$a = 10
全体としての値も10となるわけです。
多重代入
時々ある
$a = $b = $c = 10;
という書き方、これは
$a = ( $b = ( $c = 10 ) );
と解釈されます。
まず$c = 10
で$c
に10が代入され、$b
には$c = 10
の返り値10が代入され、$a
には$b = ( $c = 10 )
の返り値10が代入される、ということになり、結果として$a
・$b
・$c
すべてが10になります。
プロパティも同じです。
$c = new stdClass();
$a = $c->b = 10;
var_dump($a, $c); // $a=10, $b=stdClass{b=>10}
プロパティ型指定
実は、プロパティに型指定がある場合、返り値が変わることがあります。
class C{
public string $b;
}
$c = new C();
$a = $c->b = 10;
var_dump($a); // "10"
$c->b = 10
の返り値は10
ではなく"10"
です。
$c->b
はPHPの自動型変換でstring型に変換されますが、式全体の返り値もその変換後の値になるというわけです。
マジかよこんなん知らんかったわ。
この情報、マニュアルには記載がなく、Qiitaやその他ブログ等の記事でも全く見たことがありません。
私はプロパティフックのRFCで初めて知りました。
他にこの情報について言及されているところを見かけた人は、ぜひ教えてください。
そういえば他の言語ではどうなってるんだろう(調べる気はない)
strictモード
strictモードを有効にすることで、ほとんどの自動変換を阻止することができます。
唯一の例外はfloat型にintを渡した場合で、10
が10.0
になります。
これはstrictモード自体で元々許容されている動作であるため、仕方ないところでしょう。
実害もほぼありませんしね。
おまけ
リファレンスを使うと変数値をこっそり変更することができます。
$c = new class{
public string $b = "";
};
$b = & $c->b;
// ↑ここまでどこかに隠しておく
$a = $b = 10;
var_dump($a, $b); // $a="10", $b="10"
変数の型指定の応用です。
使い道はさっぱりわかりませんが、なんかの引っかけにでも使えるかもしれません。
Csharp
調べる気はないと言ったな。
int a;
float b;
a = b = 1; // error CS0266: Cannot implicitly convert type `float' to `int'
(b = 1).GetType(); // System.Single
int型にfloat型を突っ込もうとしてエラーになりました。
直接確認してみたところ、実際に(b=1)
の返り値はfloat型になっていました。
C#では代入式の返り値は左側の型になります。
つまり、型によって代入演算子の返り値が変わるのはPHPに固有の現象ではなく、他の言語でもよくあることのようです。
なんてこった。