26
18

Delete article

Deleted articles cannot be recovered.

Draft of this article would be also deleted.

Are you sure you want to delete this article?

More than 5 years have passed since last update.

PHPではネストした三項演算子は左から評価される

Posted at

PHPの三項演算子はネスト、つまり三項演算子の項に三項演算子を使った式を使うことができるが、PHPの三項演算子は右から順に評価されるので注意が必要だ

いろんな言語で次のようにネストした三項演算式が書ける。

true ? 1 : true ? 2 : true ? 3 : 4

多くの言語1は、次のように右から評価していく。

true ? 1 : (true ? 2 : (true ? 3 : 4))
true ? 1 : (true ? 2 :         3    ))
true ? 1 :         2
       1

しかしPHPは、左から評価していく。

((true ? 1 : true) ? 2 : true) ? 3 : 4
(        1         ? 2 : true) ? 3 : 4
                     2         ? 3 : 4
                                 3

したがって、例えば、1なら「one」、2なら「two」、3なら「three」、それ以外なら「more」をマッピングしたい気持ちで次のような三項演算子の式を書くと思いがけない罠にはまる。

$value = 2;

var_dump(
	$value === 1 ? 'one' :
	$value === 2 ? 'two' :
	$value === 3 ? 'three' : 'more'
); //=> string(5) "three"

上のコードは次のように計算された結果、"three"が答えになる。

(($v === 1 ? 'one' : $v === 2) ? 'two' : $v === 3) ? 'three' : 'more'
  ^^
((2  === 1 ? 'one' : $v === 2) ? 'two' : $v === 3) ? 'three' : 'more'
  ^------^
((false    ? 'one' : $v === 2) ? 'two' : $v === 3) ? 'three' : 'more'
                     ^^
((false    ? 'one' : 2  === 2) ? 'two' : $v === 3) ? 'three' : 'more'
                     ^------^
((false    ? 'one' : true    ) ? 'two' : $v === 3) ? 'three' : 'more'
 ^---------------------------^                                   
(true                          ? 'two' : $v === 3) ? 'three' : 'more'
^------------------------------------------------^
'two'                                              ? 'three' : 'more'
^-------------------------------------------------------------------^
'three'

上記のようなマッピングをしたい場合は、ifやswitch、連想配列など他の手立てを使ったほうがいい。

$value = 2;

var_dump(
	(function (int $value): string {
		if ($value === 1) return 'one';
		if ($value === 2) return 'two';
		if ($value === 3) return 'three';
		return 'more';
	})($value)
); //=> string(3) "two"

var_dump(
	(function (int $value): string {
		switch ($value) {
			case 1: return 'one';
			case 2: return 'two';
			case 3: return 'three';
			default: return 'more';
		}
	})($value)
); //=> string(3) "two"

var_dump(
	(function (int $value): string {
		return [
			1 => 'one',
			2 => 'two',
			3 => 'three'
		][$value] ?? 'more';
	})($value)
); //=> string(3) "two"
  1. Java, Swift, Ruby, JavaScriptなど

26
18
1

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
26
18

Delete article

Deleted articles cannot be recovered.

Draft of this article would be also deleted.

Are you sure you want to delete this article?