10
6

Delete article

Deleted articles cannot be recovered.

Draft of this article would be also deleted.

Are you sure you want to delete this article?

【PHP】代入演算子の返り値が変わることがある

Last updated at Posted at 2024-02-05

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を渡した場合で、1010.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に固有の現象ではなく、他の言語でもよくあることのようです。
なんてこった。

10
6
2

Register as a new user and use Qiita more conveniently

  1. You get articles that match your needs
  2. You can efficiently read back useful information
  3. You can use dark theme
What you can do with signing up
10
6

Delete article

Deleted articles cannot be recovered.

Draft of this article would be also deleted.

Are you sure you want to delete this article?