目次に戻る
今まで演算子 +
や =
などの説明をすっ飛ばしてきましたが、ここでようやく詳しく学習することになります。以下、演算子の優先度の高い順に紹介していきます。「優先度」とは、四則演算で言うならば乗除算が加減算より優先されるといったイメージです。
今回はボリュームぎっしりなので、一気に覚えようとはせずに徐々に触れながら覚えていく程度に思ってください。演算子絡みのよく分からない挙動・エラーに遭遇したらこのページに戻ってくればいいでしょう。
1. clone
new
(最優先)
※ この項目には未学習の内容が含まれています。
2-1. clone
オブジェクトのクローンを生成して返します。
$b = clone $a;
2-2. new
オブジェクトのインスタンスを生成して返します。
$a = new A();
2. array()
[ ]
2-1. array()
- 配列を生成して返します。
2-2. [ ]
- 配列を生成して返します。(PHP5.4以降)
- 配列のキーを指定します。
3. ++
--
~
@
(型)
3-1. ++
「インクリメント」 と呼ばれます。
3-1-1. 数値
変数を +1 する操作を行います。値に対しては使えません。
$i = 0;
$j = 0;
$i = $i + 1;
echo $i;
echo $j;
$j = $j + 1;
これは下記のように簡略化することが出来ます。
$i = 0;
$j = 0;
echo ++$i;
echo $j++;
前につけるのと後ろにつけるのでは解釈が異なるので注意してください。
前につけた場合
- インクリメントが行われる
- 操作の 後 の値が返される
後ろにつけた場合
- 操作の 前 の値が返される
- インクリメントが行われる
3-1-2. TRUE
FALSE
配列 オブジェクト リソース
何も起きません。
3-1-3. NULL
0
と見なされた後インクリメントされて 1
になります。
3-1-4. 数字以外の文字列
$s = 'X';
$a = array();
$a[] = ++$s;
$a[] = ++$s;
$a[] = ++$s;
$a[] = ++$s;
var_dump($a);
array(4) {
[0]=>
string(1) "Y"
[1]=>
string(1) "Z"
[2]=>
string(1) "AA"
[3]=>
string(2) "AB"
}
3-1-5. 数字とアルファベットで構成される文字列
$s = 'A8';
$a = array();
$a[] = ++$s;
$a[] = ++$s;
$a[] = ++$s;
var_dump($a);
array(3) {
[0]=>
string(2) "A9"
[1]=>
string(2) "B0"
[2]=>
string(2) "B1"
}
3-1-6. 【要注意】 数値と "判断される" 文字列
数値と判断された文字列はインクリメントされると、自動的に数値に変換されます。「浮動小数点数」の説明で 科学記法 について言及しましたが、実は文字列上でも該当してしまうので注意してください。この判断基準に関しては、 「緩やかな比較と厳密な比較」 で詳しく学習します。
$s = '01';
$t = '1D8';
$a = array();
$a[] = ++$s;
$a[] = ++$t;
$a[] = ++$t;
$a[] = ++$t;
var_dump($a);
array(4) {
[0]=>
int(2)
[1]=>
string(3) "1D9"
[2]=>
string(3) "1E0"
[3]=>
float(2)
}
3-2. --
「デクリメント」 と呼ばれます。
3-2-1. 数値
変数を -1 する操作を行います。値に対しては使えません。
3-2-2. TRUE
FALSE
NULL
配列 オブジェクト リソース
何も起きません。こちらには NULL
も含まれていることに注意してください。
3-2-3. 数値と判断されない文字列
何も起きません。
3-2-4. 【要注意】 数値と判断される文字列
自動的に数値に変換されます。
3-3. ~
ビット演算での 否定 を表します。
3-3-1. 数値
通常のビット反転が行われます。
3-3-2. 文字列
バイト単位でのビット反転が行われます。
3-3-3. それ以外
Fatal Error が発生します。
3-4. @
エラー制御演算子 と呼ばれます。これをつけた部分とそれより内側で発生した全てのエラーを非表示にすることが出来ます。但し、処理速度が大幅に低下するのでこれに頼るのはやめましょう。以下に例を示します。このコードはセキュリティ的に問題があるので絶対に使わないでください。
$filename = @$_GET['filename'];
$fp = @fopen($filename, 'r');
$fp = @fopen($_GET['filename'], 'r');
上記はチェックをサボりまくった例ですが、関数の実装上やむを得ない場合もあるので一概に「使うな」とは言えません。
3-5. (型)
強制的に型変換を実行する キャスト演算子 です。
4. instanceof
※ この項目には未学習の内容が含まれています。
あるオブジェクトがあるクラスのインスタンスかどうかを調べる演算子です。 型演算子 と呼ばれます。論理値 TRUE
FALSE
のどちらかが返されます。
$obj = new stdClass;
$classname = 'stdClass';
$v1 = $obj instanceof stdClass; // TRUE
$v2 = $obj instanceof $classname; // TRUE
$v3 = $obj instanceof 'stdClass'; // 文法エラー
5. !
値を論理型に変換した後、 否定(反転) したものを返します。
$v1 = !0; // TRUE
$v2 = !$v1; // FALSE
$v3 = !!$v1; // TRUE
6. *
/
%
6-1. *
/
%
乗算 と 除算 と 剰余算 を行います。結果の型は下記の条件に従います。
整数
- 剰余算の場合は無条件で整数
- 乗算か除算の場合は2つの数が整数であるとき
- 且つ、除算の場合は割り切れるとき
浮動小数点数
- 上記以外のとき
但し、ゼロで割ると Warning が発生して FALSE
になります。
6-1-1. 数値
通常の演算が行われます。
6-1-2. 文字列 TRUE
FALSE
NULL
リソース
数値に変換されます。
6-1-3. 配列 オブジェクト
Fatal Error が発生します。
7. +
-
.
7-1. +
-
(四則演算)
加算 と 減算 を行います。結果の型は乗除算と同様の法則に従います。
7-1-1. 文字列 TRUE
FALSE
NULL
リソース
数値に変換されます。
7-1-2. 配列(減算のみ)・オブジェクト
Fatal Error が発生します。
7-2. +
(配列演算)
【要注意】
これは、四則演算とは全く別の特別なものとして考えてください。
- どちらが一方でも配列でなければ Fatal Error を発生します。
- 2つの配列をキーはそのままにして結合します。
- 先に存在していたキーが優先されます。
$a = array(0 => 'A', 1 => 'B');
$b = array(1 => 'C', 2 => 'D');
var_dump($a + $b);
array(3) {
[0]=>
string(1) "A"
[1]=>
string(1) "B"
[2]=>
string(1) "D"
}
これは array_merge
関数とは全く異なる挙動であり、この違いを理解しておく必要があります。詳しくは後ほど。
7-3. .
文字列の結合 を行います。 Javaなどのノリで +
演算子を使うと文字列の結合ではなく整数変換後の 加算 が行われてしまうので注意してください。PHPにおける演算子の正しい使い方を覚えましょう。
7-3-1. 数値 TRUE
FALSE
NULL
リソース
文字列に変換されます。
7-3-1. 配列
"Array"
に変換されますが、 Notice を発生します。
7-3-2. オブジェクト
※ この項目には未学習の内容が含まれています。
- マジックメソッド
__toString
が実装されている場合、その返り値となります。 - 実装されていない場合は Catchable Fatal Error が発生します。
7-4. よくあるミス
+
-
.
の優先度は等しく、左から順に評価されていくので、下記のコードは意図したとおりに動きません。
echo 'one plus three equals ' . 1 + 3 . ' !!';
'one plus three equals 1'
という文字列に 3
が足される演算が行われてしまい、この文字列を整数に変換すると 0
になってしまうため、下記のような結果になります。
3 !!
これを避けたければ、
echo 'one plus three equals ' . (1 + 3) . ' !!';
として先に足し算を行うことを明示するか、今回のケースでは echo
の複数パラメータを渡す構文を用いて
echo 'one plus three equals ', 1 + 3, ' !!';
とすることも出来ます。後者は
echo 'one plus three equals ';
echo 1 + 3;
echo ' !!';
と全く同じことを意味します。
8. <<
>>
ビットシフト を行います。全ての値は整数型に変換されます。
# 9. <
<=
>
>=
10. ==
!=
===
!==
<>
- 2つの値を比較し、結果を論理値
TRUE
FALSE
のどちらかで返します。 - 比較規則の詳細に関しては 「緩やかな比較と厳密な比較」 で触れることにします。
11. &
12. ^
13. |
ビット演算 を行います。全ての値は整数型に変換されます。
14. &&
||
これらは 論理演算子 と呼ばれます。全ての値は論理型に変換されます。
14-1. &&
「且つ」 を表します。
14-2. ||
「又は」 を表します。
14-3. 副作用完了点について
ビット演算子と論理演算子の違いについて考えてみましょう。ビット演算で 論理値(整数の 0
1
) のみを扱うケースを考えます。
$a = false;
$b = true;
var_dump(
$a & $b,
$a && $b
);
int(0)
bool(false)
論理値としてはどちらも FALSE
になるので、どちらを用いてもいいと思われるかもしれませんが、これは 副作用 が無い場合に限定されます。
【副作用】
式が条件判定に使われるだけでなく、変数の値の変更や標準出力が起きること。
例えば下記のケースでは実行結果が異なります。
$i = array(0, 0, 0, 0);
var_dump(
++$i[0] | ++$i[1],
++$i[2] || ++$i[3],
$i
);
int(1)
bool(true)
array(4) {
[0]=>
int(1)
[1]=>
int(1)
[2]=>
int(1)
[3]=>
int(0)
}
$i[1]
と $i[3]
の値が異なっていますね。この現象について考察してみましょう。|
と ||
はどちらも左側から評価される点に着目します。
++$i[0] | ++$i[1]
ビット演算子を用いたケースでは、如何なる場合においても ++$i[0]
と ++$i[1]
は実行されます。ところが…
++$i[2] || ++$i[3]
これは ++$i[2]
が 1
となり、この式全体が TRUE
となることが確定したので、 ++$i[3]
の評価は行われなかったのです。一方、&&
の場合は式全体が FALSE
となることが確定した時点で評価は終了します。
これらの評価が終了する点のことを 副作用完了点 と呼びます。今まで何気なく書いてきたif文も、この性質を盛んに利用しています。典型的な例が isset
におけるチェックです。
if (isset($_GET['a']) && is_string($_GET['a'])) {
echo htmlspecialchars($_GET['a'], ENT_QUOTES, 'UTF-8');
}
もしこれが
if (isset($_GET['a']) & is_string($_GET['a'])) {
echo htmlspecialchars($_GET['a'], ENT_QUOTES, 'UTF-8');
}
であったとしたら、変数が未定義の場合でも is_string
が実行され、 Notice が発生してしまうことになるでしょう。
15. ?
:
$a = isset($_GET['a']) && is_string($_GET['a']) ? $_GET['a'] : '';
三項演算子 と呼ばれます。 if~else文における同一の変数に対する代入を簡略化する役割を持ちます。詳しくは「制御構造と関数」にて扱いますが、形式だけ軽く紹介しておきます。
条件式 ?
条件式がTRUEのときの値 :
条件式がFALSEのときの値
16. =
+=
-=
*=
/=
.=
%=
&=
|=
^=
<<=
>>=
=>
これらは 代入演算子 と呼ばれます。
16-1. =
最も基本的な代入演算子です。 右から左への代入を行います。代入演算子は、代入を行った後に式として代入した値を返す特性があります。
var_dump($v[] = 'A', $v);
$v[] = 'A'
は代入した "A"
を返しています。
string(1) "A"
array(1) {
[0]=>
string(1) "A"
}
これを利用して、コードを短く出来ることがあります。例えばこんなケース。
例1: 一斉に代入
$a = 0;
$b = 0;
$c = 0;
$a = $b = $c = 0;
例2: チェック中に代入
if (isset($_GET['a'])) {
$a = $_GET['a'];
if (is_string($a)) {
echo htmlspecialchars($a, ENT_QUOTES, 'UTF-8');
}
}
if (isset($_GET['a']) && is_string($a = $_GET['a'])) {
echo htmlspecialchars($a, ENT_QUOTES, 'UTF-8');
}
また、 代入される変数に隣接する演算子の優先度が変化することがあります。これも同様に簡略化に役立つことがあります。
例3: 代入結果の否定
strlen
は文字列のバイト長を返す関数です。
strlen
http://php.net/manual/ja/function.strlen.php
$str = 'hogehoge';
if (!($length = strlen($str))) {
echo "This string is empty";
} else {
echo "This string has {$length} bytes.";
}
$str = 'hogehoge';
if (!$length = strlen($str)) {
echo "This string is empty";
} else {
echo "This string has {$length} bytes.";
}
16-2. +=
-=
*=
/=
.=
%=
&=
|=
^=
<<=
>>=
これらは全て計算した結果をもう一度代入し直すという動作をします。
$i = $j = $k = 0;
var_dump(
$i = $i + 1,
$j += 1,
++$k
);
上の3つの式は全て等価です。
int(1)
int(1)
int(1)
なお、$k++
とするのは意味が異なるので注意してください。
16-3. =>
これは一応代入演算子には分類されますが、 ダブルアロー演算子 の名前の方が有名です。配列の初期化代入にのみ使用され、他とは性質が大きく異なるので、どちらかと言えば言語構文に近いものとして認知すべきでしょう。
$data = array(
'a' => 'A',
'b' => 'B',
);
17. and
18. xor
19. or
これらの役割はそれぞれ &&
^
||
と全く同じですが、優先度が異なります。
&&
^
||
> 代入演算子 > and
xor
or
例. ファイルポインタのオープン
die
はスクリプトの実行を強制的に中断する言語構文です。下記の例ではファイルが開けなかったときにエラーメッセージを出して強制終了します。
$fp = @fopen('data.txt', 'r') or die('Failed to open data.txt');
どうして ^^
って存在しないの?
ここに目をつけてくれた人はなかなか鋭いですね。 &&
演算子や ||
演算子は式の左側を見ただけで結果を決めることがあると先ほど紹介しましたが、それに倣って ^^
演算子を実装するとしても 「どちらか一方が TRUE
ならば~」 という条件になるので、両側を見ることが確定してしまっており、結果的にはビット演算の ^
で十分だと言えるのが要因です。
20. ,
さまざまな利用法(マニュアルよりそのまま言葉引用)
演算子は以上です。お疲れ様でした、徐々に覚えていきましょう。次回は 「緩やかな比較と厳密な比較」 について学びます。