MEMORVA

PHPの三項演算子はどういうときに使えば良いのか

更新:

以前、Googleで「三項演算子」と検索したら「使うな」というサジェストが表示されたことがあった。 三項演算子は「?」や「:」で並べる書き方が他の演算子や構文と比べると少し異質な印象がある。 それが嫌われる原因なのか、たくさん結合すると見にくいから嫌われるのかは分からない。

私も昔は積極的には三項演算子を使っていなかったが、最近になってわりと使うようになった。

PHPはバージョンが上がるごとに型や未定義の変数について厳格になってきており、エラーが発生することもある。

例えば、以下のように連想配列で存在しないキーを指定して値を取得しようとすると警告(Warning)が出る。

$list = array('a' => 'mikan', 'b' => 'ringo');
$res = $list['c'];
echo 'Res: ' . $res;

そこで if 文と isset() を使って変数をチェックしてから値を取得すると以下のようになる。

$list = array('a' => 'mikan', 'b' => 'ringo');

if(isset($list['c'])){
	$res = $list['c'];
}else{
	$res = '';
}

echo 'Res: ' . $res;

$res = ''; (空文字)としているのは、未定義だと後の echo で警告が出るため。 if より前に定義しておいても良い。

isset() 以外に empty() でもチェックできる。 また、配列の場合は array_key_exists() という関数でキーの有無が確認できる。 定数の場合は defined() という関数が使える。

ただ、変数のチェックがたくさんある場合、コードの行数が多くなる。 まあ、if文を1行で書いたり、独自の関数を作ってチェックしても良いが。

そういうときに三項演算子が有用。 上の例を以下のように書き換える。

$list = array('a' => 'mikan', 'b' => 'ringo');
$res = isset($list['c']) ? $list['c'] : '';
echo 'Res: ' . $res;

三項演算子の基本の書式は「条件式 ? 真の場合の値 : 偽の場合の値」となっている。 ここで言うと「isset($list['c']) ? $list['c'] : ''」の部分が該当する。

このとき三項演算子は、そこに記述した真または偽の値を返す。 この例ではそれを変数 $res に代入している。 1行で判別と代入を同時に行っている。

ここで重要なのは、値やキーがあるかどうかではなく、警告やエラーを回避するということ。 そのために三項演算子を活用している。

なお、エラーの表示(error_reporting())を非表示にしていると警告は表示されないが、他のエラーの原因になる可能性もあるため、事前に変数をチェックしておくと良いかもしれない。

$_GET、$_POST、$_SERVER

ウェブサイトを制作していると $_GET、$_POST、$_SERVER といった変数をよく使う。

例えば、$_GET で引数(パラメータ)を受け取る場合、以下のように書く。

$test = $_GET['test'];
echo 'Test: ' . $test;

これも上述の連想配列の例と同じで、test という引数が存在しない場合、警告が出る。 $_GET や $_POST で引数を受け取る場合、必ずしもその引数が存在するとは限らない。

そこで if 文でチェックすると以下のようになる。

if(isset($_GET['test'])){
	$test =  $_GET['test'];
}else{
	$test = '';
}

echo 'Test: ' . $test;

これも三項演算子で書くと以下のようになる。

$test = isset($_GET['test']) ?  $_GET['test'] : '';
echo 'Test: ' . $test;

サーバーの環境変数はいろいろあるが、必ずしも必要な変数やキーが存在するとは限らない。 例えば、ページの参照元(リファラ)は $_SERVER['HTTP_REFERER'] で取得できるが、リファラがない場合、この値(HTTP_REFERERキー)自体がない。 そこで三項演算子で取得する。

$http_referer = isset($_SERVER['HTTP_REFERER']) ?  $_SERVER['HTTP_REFERER'] : '';
echo 'HTTP_REFERER: ' . $http_referer;

上述のように、これらも警告やエラーを回避することを目的としている。

他の言語

ここではPHPについてサンプルを書いたが、JavaScriptやPythonなど他の言語でも考え方は同じ。 ただし、言語によって三項演算子の書式が異なる場合がある。

年々、いろいろな言語で型や未定義の変数についてうるさくなっている気がしなくもないので、そういうときに三項演算子が有用かもしれない。