演算子とは?
例えば、四則演算をする際に使用する「+」(足す)、「-」(引く)、「*」(掛ける)、「/」(割る)などがそれにあたります。
上記のコード例では、「=」と「+」を使って3と、4という一つ以上の値を受け取り、7という別の値を生み出していますね。
また、演算子をオペレーター、演算の対象となる値や変数のことをオペランドと言います。
先程の式でいうと、
オペレーターである代数演算子「+」のオペランドが、3 と 4 で、
オペレーターである代入演算子「=」のオペランドが、変数 numと、部分式 3 + 4 になります。
そして、演算子には以下に示すように、他にも様々な種類があります。
代数演算子 | 代入演算子 | ビット演算子 | 比較演算子 |
エラー制御演算子 | 実行演算子 | 加算子/減算子 | 論理演算子 |
文字列演算子 | 配列演算子 | 型演算子 | キャスト演算子 |
宇宙船演算子 | NULL合体演算子 | 三項演算子 |
この記事では
phpで使用する演算子の種類と使い方について、初心者向けに解説していきます。
代数演算子とは
代数演算子は、算術演算子ともいわれ、「+」(足す)、「-」(引く)、「*」(掛ける)、「/」(割る)などの一般的な計算を行う際に使用します。(算術演算子 - Manual)
演算子 | 名前 | 例 | 計算結果 |
+ | 加算 | 2 + 3 | 6 |
- | 減算 | 8 - 4 | 4 |
* | 乗算 | 2 * 3 | 6 |
/ | 除算 | 6 / 3 | 2 |
% | 剰余 | 9 % 2 | 1 |
** | 累乗 | 2 ** 3 | 8 |
数値を掛ける乗算演算子「*」は「×」ではなく、数値を割る除算演算子「/」は「÷」ではないので注意してください。
また、剰余演算子「%」は何に使用するの?と思う方がいるかもしれませんが、制御文(if文やfor文など)を使って、ある整数が偶数か奇数かを判別するときや、単に除算の余りを求めるときなどに使用します。
代入演算子とは
代入演算子
代入演算子とは、「=」(イコール)のことです。(代入演算子 - Manual)
しかし、プログラミング世界の「=」は等しいという意味ではなく、右側の値をコピーして左側の変数に代入するという意味になります。
</>php<?php $num1 = 6 $num2 = $num1 + 1; echo $num1; // 6 echo $num2; // 7 ?>
$num2が「7」を出力するのはもちろんですが、最初に$num1に代入された「6」は、1を足して$num2に代入した後も「6」のままです。
最初に変数$num1に代入された6がなくなるわけではありませんので注意してください。
複合代入演算子
複合代入演算子とは、代入演算子「=」と代数演算子「+」「-」「*」「/」などの、その他の演算子を複合(2以上のものが1つになること)した演算子です。
複合代入演算子を使うことにより、少しだけコードを短く書くことができます。
演算子 | 名前 | 例 | 説明 | 計算結果 ( $num = 5; の場合) |
+= | 加算 | $num += 3 | $num = ($num + 3)と同じ | 8 |
-= | 減算 | $num -= 2 | $num = ($num - 2)と同じ | 3 |
*= | 乗算 | $num *= 3 | $num = ($num * 3)と同じ | 15 |
/= | 除算 | $num /= 2 | $num = ($num / 3)と同じ | 2.5 |
%= | 剰余 | $num %= 3 | $num = ($num % 3)と同じ | 2 |
**= | 累乗 | $num **= 2 | $num = ($num ** 2)と同じ | 25 |
.= | 文字列の結合 | $num .= 2 | $num = ($num ** 2)と同じ | 52 |
例えば、変数自身に1を足したい場合は、代入演算子「=」と代数演算子「+」を使って次のように書きますが…
</>php<?php $num = $num + 1; ?>
複合代入演算子を使用すると、
</>php<?php $num =+ 1; ?>
代入演算子「=」と代数演算子「+」を一つにまとめて記述することができます。
比較演算子とは
比較演算子は、値や文字などを比較する演算子です。(比較演算子 - Manual)
「aはbより大きい」や「aとbは等しい」といった2つの値の大小を比較したり、値や文字列などが等しいかを判定し、等しければ「true」を、そうでない場合は「false」を返します。
演算子 | 例 | 説明 |
> | a > b | aがbより大きい値のときにtrueを返す |
< | a < b | aがbより小さい値のときにtrueを返す |
>= | a >= b | aがb以上の値のときにtrueを返す |
<= | a <= b | aがb以下の値のときにtrueを返す |
== | a == b | aとbの値が等しいときにtrueを返す |
=== | a === b | aとbの値も型も等しいときにtrueを返す |
!= または <> | a != b または a <> b | aとbの値が等しくないときにtrueを返す |
!== | a !== b | aとbの値または型が等しくないときにtrueを返す |
比較演算子は、主にif文やfor文などの制御構文の条件式で表示結果を切り分ける際に使用されることが多いです。
値の大小を比較する場合
比較演算子を使って値の大小を比較する場合に使用する演算子は、以下の通りです。
演算子 | 例 | 説明 |
> | a > b | aがbより大きい値のときにtrueを返す |
< | a < b | aがbより小さい値のときにtrueを返す |
>= | a >= b | aがb以上の値のときにtrueを返す |
<= | a <= b | aがb以下の値のときにtrueを返す |
例として、20歳以上であれば「田中さんは、成人しています。」、20歳未満であれば「田中さんは、未成年です。」という文章を、比較演算子を使って表示してみましょう。
</>php<?php
$age = 20;
if($age >= 20){
echo "田中さんは、成人しています。";
} elseif($age < 20) {
echo "田中さんは、未成年です。";
} ?>
「$age >= 20」は、20を含むので「true」となり「田中さんは、成人しています。」と表示されていますね。
値が「等しい」「等しくない」を比較する場合
比較演算子を使って値が等しい、または等しくないかを比較する場合に使用する演算子は、以下の通りです。
演算子 | 例 | 説明 |
== | a == b | aとbの値が等しいときにtrueを返す |
=== | a === b | aとbの値もデータ型も等しいときにtrueを返す |
!= (<>) | a != b (a <> b) | aとbの値が等しくないときにtrueを返す |
!== | a !== b | aとbの値またはデータ型が等しくないときにtrueを返す |
例として、「==」と「===」を使用し、数字の20と文字列の「20」 を比較してみましょう。
</>php<?php
$a = 20;
if($a === '20'){
echo "{$a}と文字列の「20」は値と型も等しいです。";
} elseif ($a == '20'){
echo "{$a}と文字列の「20」は値が等しいです。";
} ?>
値は等しいが、数値型と文字列型でデータ型が違うので、「$a == '20'」のみがtrueとなり「20と文字列の「20」は値が等しいです。」が出力されます。
次に、「!=」と「!==」を使用して、数字の20と文字列の「20」を比較してみましょう。
</>php<?php
$a = 20;
if($a != '20'){
echo "{$a}と文字列の「20」は値が等しくありません。";
} elseif ($a !== '20'){
echo "{$a}と文字列の「20」は値または型が等しくありません。";
} ?>
値は等しいが、数値型と文字列型でデータ型が違うので、「$a !== '20'」のみがtrueとなり「20と文字列の「20」は値または型が等しくありません。」が出力されます。
論理演算子とは
論理演算子は、複数の条件式や真偽値を評価し、その結果をtrueまたはfalseで返します。(論理演算子 - Manual)
演算子 | 例 | 名前 | 説明 |
&& | a && b | 論理積 | aかつbの両方がtrueのときにtrueを返す |
and | a and b | 論理積 | 同上 |
|| | a || b | 論理和 | aまたはb、またはab両方がtrueのときにtrueを返す |
or | a or b | 論理和 | 同上 |
xor | a xor b | 排他的論理和 | aまたはbのどちらか一方だけがtrueのときにtrueを返す |
! | !a | 否定 | aがtrueならばfalse、falseならばtrueを返す |
論理積「&&」「and」
論理積の「&&」と「and」は左右のオペランドの両方がtrueの場合trueを返し、それ以外はfalseを返します。
演算子 | 例 | 名前※ | 説明 |
&& | a && b | 論理積 | aかつbの両方がtrueのときにtrueを返す |
and | a and b | 論理積 | 同上 |
例として、if文の中で「&&」を使用して、数値と文字列の「10」を「==」で比較した2つの式を評価してみましょう。
</>php<?php
$num = 10;
$a = 10;
$b = '10';
if(($num == $a) && ($num == $b)){
echo 'TRUEです。'; //こちらが表示される
} else {
echo 'FALSEです。';
} ?>
($num == $a)と($num == $b)はどちらも型までは判定しないため、値が等しいとみなされtrueとなり「TRUEです。」が表示されます。
次に、if文の中で「&&」を使用して、数値と文字列の「10」を「===」で比較した2つの式を評価してみましょう。
</>php<?php
$num = 10;
$a = 10;
$b = '10';
if(($num === $a) && ($num === $b)){
echo 'TRUEです。';
} else {
echo 'FALSEです。'; //こちらが表示される
} ?>
今回は、($num === $b)は型も比較されてしまうためFALSEとなり「FALSEです。」が表示されます。
もちろん、「&&」の代わりに、「and」を使用しても結果は同じです。
しかし、「&&」と「and」は、結合の優先度に違いがあるため、ある条件下では結果が異なるので注意が必要です。
</>php<?php
$test1 = true && false;
$test2 = true and false;
var_dump($test1);
echo "<br>";
var_dump($test2); ?>
「&&」は「=」に比べ優先順位が高いので、通常通り「true && false」の結果が変数に入ります。
しかし、
「and」は「=」に比べ優先順位が低いので、「$test2 = true」が先に計算されるためtrueが変数に入ってくることになります。
このように、思わぬ結果を招いてしまうことがあるため、特に理由がなければ文字の「and」ではなく記号の「&&」を使用するようにしましょう。
この現象は次に紹介する論理和「||」「or」でも同様です。
論理和「||」「or」
論理和の「||」と「or」は、左右のどちらか一方のオペランドがtrueの場合や、左右両方のオペランドがtrueの場合にtrueを返し、それ以外の場合はfalseを返します。
演算子 | 例 | 名前※ | 説明 |
|| | a || b | 論理和 | aまたはb、またはab両方がtrueのときにtrueを返す |
or | a or b | 論理和 | 同上 |
if文の中で「||」を使用して、数値と文字列の「10」を「===」で比較した2つの式を評価してみましょう。
</>php<?php
$num = 10;
$a = 10;
$b = '10';
if(($num === $a) || ($num === $b)){
echo 'TRUEです。'; //こちらが表示される
} else {
echo 'FALSEです。';
} ?>
($num === $b)がfalseですが、($num === $a)がtrueのため、trueが返されます。
今回は「||」を使用しましたが、もちろん「or」を使用しても同様の結果になります。
前項の論理積でも説明したように、「||」と「or」は、結合の優先度に違いがあるため、使用する場合は注意が必要です。
排他的論理和「xor」
排他的論理和の「xor」は、左右のどちらか片方だけがtrueのときにtrueを返します。
演算子 | 例 | 名前 | 説明 |
xor | a xor b | 排他的論理和 | aまたはbのどちらか一方だけがtrueのときにtrueを返す。 |
論理和と似ていますが、左右両方のオペランドがtrueの場合はfalseを返す点が異なります。
if文の中で「xor」を使用して、数値と文字列の「10」を「===」で比較した2つの式を評価してみましょう。
</>php<?php $num = 10;
$a = 10;
$b = '10';
if(($num === $a) xor ($num === $b)){
echo 'TRUEです。'; //こちらが表示される
} else {
echo 'FALSEです。';
} ?>
条件式のうち、片方だけ($num === $a)がtrueなので、trueを返します。
次に、同じコードで、緩やかな比較「==」を使った場合はどうなるか確認してみましょう。
</>php<?php $num = 10;
$a = 10;
$b = '10';
if(($num == $a) xor ($num == $b)){
echo 'TRUEです。';
} else {
echo 'FALSEです。'; //こちらが表示される
} ?>
($num == $a) も ($num == $b) のどちらもtrueなのでfalseが返されましたね。
このように排他的論理和は、どちらか一方がtrueの時のみtrueを返します。
否定「!」
否定の「!」は、「!a」と記述した場合、aがtrueならばfalseを、falseならtrueを返します。
演算子 | 例 | 名前 | 説明 |
! | !a | 否定 | aがtrueならばfalse、falseならばtrueを返す。 |
例として、数値と文字列の「10」を「===」を使って比較した条件式に、否定「!」を使うとどうなるか確認してみましょう。
</>php<?php $num = 10;
$a = '10';
if(!($num === $a)){
echo 'TRUEです。'; //こちらが表示される
} else {
echo 'FALSEです。';
} ?>
($num === $a)はfalseですが、否定「!」があるためtrueとなり「TRUEです。」が表示されます。
緩やかな比較「==」を使った例も確認してみましょう。
</>php<?php $num = 10;
$a = '10';
if(!($num == $a)){
echo 'TRUEです。';
} else {
echo 'FALSEです。'; //こちらが表示される
} ?>
($num == $a)を評価するのでtrueですが、否定「!」があるのでfalseとなり「FALSEです。」が表示されます。
加算子(インクリメント)と減算子(デクリメント)
インクリメント(加算子)は、変数の値を1つ増やし、デクリメント(減算子)は変数の値を1つ減らします。(加算子/減算子 - Manual)
演算子 | 名前 | 説明 |
++$a | 前置加算子 | $a に 1 を加え、$a を返します。 |
$a++ | 後置加算子 | $a を返し、$a に1を加えます。 |
--$a | 前置減算子 | $a から 1 を引き、$a を返します。 |
$a-- | 後置減算子 | $a を返し、$a から 1 を引きます。 |
しかし、「++」「--」は、変数の前にある場合と後ろにある場合とで、挙動が変わるので注意が必要です。
まずは、「++$a」前置加算子を使った例を確認してみましょう。
</>php<?php
$a = 5;
echo ++$a; ?>
5に1が加えられ、6が返されました。
次に、「$a++」後置加算子を見てみましょう。
</>php<?php
$a = 5;
echo $a++ ; echo "<br>";
echo $a; ?>
1つ目の変数は変数がそのまま返されるので「5」になり、2つ目の変数は1が加えられるので「6」が返ります。
三項演算子とは
三項演算子は、3つのオペランドを使用する条件演算子です。
条件式を評価し、trueの場合は「:」の左側の式を返し、falseの場合は右側の式を返します。
例として、三項演算子を使って、年齢が「20」以上の場合は「成人しています。」、それ以外の場合は「未成年です。」という文を作ってみましょう。
</>php<?php
$age = 19;
echo $age >= 20 ? "成人しています。" : "未成年です。" ; ?>
最初に「$age = 19;」を代入しているので、「$age >= 20」でfalseとなり、「未成年です。」が表示されました。
文字列演算子とは
文字列演算子は左右のオペランドを連結したものを返す結合演算子「.(ドット)」と、
左のオペランドに右のオペランドを追加したものを返す結合代入演算子「.=(ドットイコール)」の2種類があります。(文字列演算子 - Manual)
まずは、結合演算子「.(ドット)」から見てみましょう。
「田中さんは」という文章と、「成人しています。」という文章を連結してみます。
</>php<?php
$str = "田中さんは、" . "成人しています。";
echo $str; ?>
「.」(ドット)の左辺の「田中さんは、」という文字列と、右辺の「成人しています。」が一つの文章として返されていますね。
次に、結合代入演算子「.=(ドットイコール)」の使用例を見てみましょう。
「田中さんは、成人しています。」という文字列の入った変数に、「歳は22です。」という文字列と数値が入った変数を追加してみます。
</>php<?php
$str = "田中さんは、成人しています。";
$a = "歳は" . 22 . "です。"; $str .= $a;
echo $str; ?>
変数である$strに、文字列を連結することができました。
ちなみに、数値を「.」(ドット)で連結すると自動的に文字列として扱われます。(今回は、数値の「22」を連結しています。)
この場合、変数「$str」に「$a」を代入しているため、「$a」をechoで出力しようとしても「Parse error: syntax error, unexpected variable "$a"」とエラー表示されてしまうので注意して下さい。
もし同じ内容を「.=(ドットイコール)」の代わりに「.」(ドット)を使用して表示したい場合は、「$str .= $a;」の部分を、「echo $str.$a;」にする必要があります。
配列演算子とは
配列演算子は、配列型のデータ同士を結合したり比較することができます。(配列演算子 - Manual)
演算子 | 名前 | 例 | 説明 |
+ | 結合 | $a + $b | 配列aと配列bを結合して返す |
== | 同等 | a == b | 配列aと配列bのキー / 値のペアが等しいときにtrueを返す |
=== | 同一 | a === b | 配列aと配列bのキー / 値のペアと並び順と型が全て等しいときにtrueを返す |
!= または <> | 等しくない | a !== b または a <> b | 配列aと配列bが等しくないときにtrueを返す |
!== | 同一でない | a !=== b | 配列aと配列bが同一でないときにtrueを返す |
最後の「!==」の説明の同一でないときとは、キー/値のペア、並び順、型の全て、又はどれかが違う場合を指します。
結合「+」
結合「+」は、「$a + $b」と記述した場合、配列aと配列bを結合して返します。
演算子 | 名前 | 例 | 説明 |
+ | 結合 | $a + $b | 配列$aと配列$bを結合して返す |
しかし、両方の配列に存在するキーについては左側の内容が優先され、右側は無視されますので注意が必要です。
例として、「りんご、バナナ」の入った配列と、「みかん、いちご」の入った2つの配列を「+」を使用して一つの配列に結合してみましょう。
</>php<?php
$a = array("a" => "リンゴ", "b" => "バナナ");
$b = array("b" => "みかん", "c" => "いちご");
$c = $a + $b;
var_dump($c); ?>
どちらの配列も中身の要素が2つですが、結果の要素数は4つではなく3つになっています。
これは先ほど説明したように、同じキーが含まれていたためです。
今回はキー「b」がどちらの配列にも含まれていたので、左側の配列($a)の「バナナ」が優先されました。
同等「==」、同一「===」
同等「==」、同一「===」は、配列同士を比較し、等しい場合や同一の場合にtrueまたはfalseを返します。
演算子 | 名前 | 例 | 説明 |
== | 同等 | a == b | 配列aと配列bのキー / 値のペアが等しいときにtrueを返す |
=== | 同一 | a === b | 配列aと配列bのキー / 値のペアと並び順と型が全て等しいときにtrueを返す |
「文字列のリンゴと文字列の10」の入った配列と、「文字列のリンゴと数値の10」の入った配列を同等「==」を使用して比較してみましょう。
</>php<?php
$a = array("a" => "リンゴ", "b" => "10");
$b = array("a" => "リンゴ", "b" => 10);
if($a == $b){
echo "配列aと配列bは等しいです。";
} else {
echo "配列aと配列bは等しくありません。";
} ?>
「==」は型の判定までは行いません。
キー「b」の値「10」が、数値型と文字列型で型が異なりますが、値が同じなのでtrueが返されました。
次に、同一「===」を使用して比較してみましょう。
</>php<?php
$a = array("a" => "リンゴ", "b" => "10");
$b = array("a" => "リンゴ", "b" => 10);
if($a === $b){
echo "配列aと配列bは同一です。";
} else {
echo "配列aと配列bは同一ではありません。";
} ?>
キー/値のペアも並び順も等しいですが、キー「b」の値「10」が、値数値型と文字列型で型が異なっているため、falseが返されました。
等しくない「!=」、同一でない「!==」
「!=」と「!==」は、配列同士を比較し、等しくない場合や同一でない場合にtrueまたはfalseを返します。
演算子 | 名前 | 例 | 説明 |
!= または <> | 等しくない | a !== b または a <> b | 配列aと配列bが等しくないときにtrueを返す |
!== | 同一でない | a !=== b | 配列aと配列bが同一でないときにtrueを返す |
まずは、「文字列のリンゴと文字列の10」の入った配列と、「文字列のリンゴと数値の10」の入った配列を同等「!=」を使用して比較してみましょう。
</>php<?php
$a = array("a" => "リンゴ", "b" => "10");
$b = array("a" => "リンゴ", "b" => 10);
if($a != $b){
echo "配列aと配列bは等しいです。";
} else {
echo "配列aと配列bは等しくありません。";
} ?>
「!=」は型の判定までは行いません。
キー「b」の値「10」が、数値型と文字列型で型が異なりますが値が等しいので、falseが返されました。
次に、「!==」を使用して比較してみましょう。
</>php<?php
$a = array("a" => "リンゴ", "b" => "10");
$b = array("a" => "リンゴ", "b" => 10);
if($a !== $b){
echo "配列aと配列bは同一です。";
} else {
echo "配列aと配列bは同一ではありません。";
} ?>
キー/値のペアも並び順も等しいですが、キー「b」の値「10」が、値数値型と文字列型で型が異なっているため、trueが返されました。
キャスト演算子とは
キャスト演算子は、演算子の右辺の値のデータ型を指定したデータ型に変換する演算子です。(型の相互変換 - Manual)
phpは、プログラムの文脈に応じて、変数の型が自動変換(型のジャグリング)されます。
しかし、型宣言を必要としないため、型を意識することなく書くことができるというメリットがありますが、型を指定してプログラムを書きたい場合もあります。
型を指定したい場合は、以下のキャスト演算子を使用することで指定することができます。
演算子 | 型の名前 | 演算子 | 型の名前 |
(int),(integer) | 整数型 | (string) | 文字列型 |
(bool), (boolean) | 論理型 | (array) | 配列型 |
(float), (double), (real) | 浮動小数点数型 | (object) | オブジェクト型 |
※ (unset) によるキャストは、値に NULL 値を代入することと同じです。 PHP 7.2.0 以降推奨され、PHP 8.0.0 で削除されました。
まずは整数型の「10」を、文字列に変換してみましょう。
</>php<?php
$a = 10;
$b = (string)$a; var_dump($a); echo "<br>\n";
var_dump($b); ?>
数値型の「10」が文字列型に変換されていますね。
次に、残りの全ての型に変換してみましょう。
</>php<?php
$a = 10;
$a = (bool)$a;
echo var_dump($a)."<br>\n";
$a = (array)$a;
echo var_dump($a)."<br>\n";
$a = (float)$a;
echo var_dump($a)."<br>\n";
$a = (object)$a;
echo var_dump($a)."<br>\n"; ?>
指定された通りに、数値型から各型に変換されています。
型演算子とは
型演算子「instanceof」は、指定した変数が、あるクラスのインスタンスかを調べることができる演算子です。(型演算子 - Manual)
変数が、指定したクラスのインスタンスである場合はtrue、そうでない場合はfalseを返します。
他にも、特定の親クラスを継承したクラスのインスタンスかを調べることができたり、特定のインターフェイスを実装したクラスのインスタンスかどうかを調べることもできます。
特定のクラスのインスタンスかを調べる場合
型演算子「instanceof」の左辺の変数が右辺に指定したクラス名のクラスのインスタンスかを調べてみましょう。
</>php<?php class Class01 { } class Class02 { } $a = new Class01; var_dump($a instanceof Class01); var_dump($a instanceof Class02); ?>
「new」演算子を使って作ったインスタンス「Class01」を、instanceofで判定しています。
一つ目のvar_dumpでは「Class01」のクラスのインスタンスなのでtrueが返り、
二つ目のvar_dumpでは「Class02」のクラスのインスタンスではないのでfalseが返りました。
特定の親クラスを継承したクラスのインスタンスかを調べる場合
型演算子「instanceof」は、左辺の変数が、特定の親クラスを継承したクラスのインスタンスであるかを調べることもできます。
</>php<?php
class ParentClass
{
}
class Class01 extends ParentClass
{
}
$a = new Class01;
var_dump($a instanceof Class01);
var_dump($a instanceof ParentClass); ?>
「extends」使って親クラス「ParentClass」を継承したインスタンス「Class01」を、instanceofで判定しています。
一つ目のvar_dumpでは「Class01」のクラスのインスタンスなのでtrueが返り、
二つ目のvar_dumpでは親クラス「ParentClass」を継承したクラスのインスタンスなのでtrueが返りました。
特定のインターフェイスを実装したクラスのインスタンスかを調べる場合
型演算子「instanceof」の、左辺の変数が、特定のインターフェイスを実装したクラスのインスタンスであるかを調べることもできます。
</>php<?php interface MyInterface { } class Class01 implements MyInterface { } $a = new Class01; var_dump($a instanceof Class01); var_dump($a instanceof MyInterface); ?>
インターフェイス「Myinterface」を使って実装した親クラス「ParentClass」を継承したインスタンス「Class01」を、instanceofで判定しています。
一つ目のvar_dumpでは「Class01」のクラスのインスタンスなのでtrueが返り、
二つ目のvar_dumpではインターフェイス「Myinterfase」を実装したクラスのインスタンスなのでtrueが返りました。
ビット演算子とは
ビット演算子とは、数値をビット形式にして処理することができる演算子です。(ビット演算子 - Manual)
ビットとは「0」か「1」で構成されるコンピューター世界の最小単位で、2進数で表現するものです。
ビット演算子には以下の6種類があります。
演算子 | 名前 | 例 | 結果 |
& | ビット積 | $a & $b | $a と $b の各桁同士を比較し、両方が1なら1、そうでなければ0を返す。 |
| | ビット和 | $a | $b | $a と$b の各桁同士を比較し、どちらかが1なら1、そうでなければ0を返す。 |
^ | 排他的論理和 | $a ^ $b | $a と $b の各桁同士を比較し、片方だけが1なら1、そうでなければ0を返す。 |
~ | 否定 | ~ $a | $a の各桁の1と0を逆転させる。 |
<< | 左シフト | $a << $b | $a のビットを左に $b 桁シフトする (各シフトは "2をかける" ことを意味します) |
>> | 右シフト | $a >> $b | $a のビットを右に $b 桁シフトします (各シフトは "2で割る" ことを意味します) |
ビット積「&」、ビット和「|」 、排他的論理和「^」、否定「~」
ビット演算子の中でも、ビット積「&」、ビット和「|」、排他的論理和「^」、否定「~」の4つは、数値を2進数にして各桁を比較して演算します。
演算子 | 名前 | 例 | 結果 |
& | ビット積 | $a & $b | $a と $b の各桁同士を比較し、両方が1なら1、そうでなければ0を返す。 |
| | ビット和 | $a | $b | $a と$b の各桁同士を比較し、どちらかが1なら1、そうでなければ0を返す。 |
^ | 排他的論理和 | $a ^ $b | $a と $b の各桁同士を比較し、片方だけが1なら1、そうでなければ0を返す。 |
~ | 否定 | ~ $a | $a の各桁の1と0を逆転させる。 |
と、聞いても最初はよくわからないと思いますので「ビット積」を例に見てみましょう。
ビット積「&」は、「$a & $b」のように2つの値の間に配置します。
そして、&の前後にある2つの数値のビットを比較し、同じ位置に1がある場合に1を、そうでない場合は0を返します。
ビット演算子は、私たちが普段使っている10進数の数値を2進数に置き換えて処理をしますので、例えば「470」と「350」をビット論理積で比較する場合は、
「111 010 110」と「101 011 110」に変換してから、同じ位置にある「1」と「0」を比較します。
では、実際に「&」を使用して処理してみましょう。
</>php<?php $a = 470; $b = 350; echo $a & $b; //342 ?>
表示結果は「342」になりますが、計算過程は以下のようになります。
2進数である「101 010 110」が10進数に変換されて「342」が表示されていることがわかると思います。
ちなみに2進数の桁数が合わない場合は、「0」として処理されます。
このように、ビット積、ビット和、排他的論理和、否定の4つは、数値を2進数にして各桁を比較します。
ビット積「&」は、各桁同士を比較し、両方が1なら1、そうでなければ0を返します。
ビット和「|」は、各桁同士を比較し、どちらかが1なら1、そうでなければ0を返します。
排他的論理和「^」は、各桁同士を比較し、片方だけが1なら1、そうでなければ0を返します。
否定「~」は、各桁の1と0を逆転させます。
左シフト、右シフト
左シフト「<<」と右シフト「>>」は、数値の桁をシフト(移動)する演算子です。
左辺の数値に対して、2進数でどれだけ桁数を移動するかを右辺で指定します。
演算子 | 名前 | 例 | 結果 |
<< | 左シフト | $a << $b | $a のビットを左に $b 桁シフトする (各シフトは "2をかける" ことを意味します) |
>> | 右シフト | $a >> $b | $a のビットを右に $b 桁シフトします (各シフトは "2で割る" ことを意味します) |
と、聞いても最初はあまりピンと来ないと思います。
まずは左シフト「<<」を使って42(2進数では101010)という数値を左に3桁移動した場合を例に見てみましょう。
</>php<?php
$a = 42;
echo $a << 3; ?>
42を3桁左に移動させるので、42000が返ると思いましたか?違います。
42を二進数に変換してから3桁左に移動させて、再度十進数に変換して返すので336が返ります。
次に右シフト「>>」をみてみましょう。
右シフト「>>」を使って同じく42(2進数では101010)という数値を右に3桁移動した場合を例に見てみましょう。
</>php<?php
$a = 42;
echo $a >> 3; // 5 ?>
42を3桁右に移動させるので、0.042が返ると思いましたか?こちらも違います。
42を二進数に変換してから3桁右に移動させて、再度十進数に変換して返すので5が返ります。
二進数に変換した後、右に3桁移動した場合は、下3桁が消え、残りの数値を処理する点に注意してください。
宇宙船演算子とは
宇宙船演算子「<=>」は、2つの数値を比較し、左辺が右辺より大きければ1を、小さければ-1を、等しければ0を返します。(新機能 - Manual)
</>php<?php
$num = 10;
$a = 1;
$b = 10;
$c = 100;
echo $num <=> $a; echo "<br>\n";
echo $num <=> $b; echo "<br>\n";
echo $num <=> $c; ?>
usort関数を使った配列の並び替え
宇宙船演算子「<=>」の使い方として考えられるのが、usort関数と組み合わせた配列の並び替えです。
usort関数は、並び替えたい配列を第一引数に、ユーザー定義の比較関数を第二引数に指定して配列の並び替えを行います。
ユーザー定義関数とは、最初からphpに用意されている関数ではなく自分で作成する関数のことで、ここでは「並び替えのルール」を記述します。
しかし、usort関数で呼んだ関数の比較の結果は、「正数 / 負数 / 0」 で返す必要があります。
そこで宇宙船演算子「<=>」の出番です。
例として、「4、2、3、1、6、5、2、6」とランダムに並んだ数値を並び替えてみましょう。
</>php<?php
$nums = [4,2,3,1,6,5,2,6];
usort($nums, function($a,$b){
return $a <=> $b;
});
echo print_r($nums); ?>
並びがバラバラだった数値を並べ替えることができました。
実行演算子とは
実行演算子「`」(バッククォート)は、バッククォートを中身を、シェルコマンドとして実行します。これはshell_exec()と同じ働きをします。(実行演算子 - Manual)
ちなみにシェルとは、windowsでいう「コマンドプロント」のようなものです。
</>php<?php $output = ` ls `; echo "<pre>$output</pre>"; ?>
今現在いるのフォルダのパスが表示されました。(シェルコマンド「pmw」は、カレントディレクトリ(現在のフォルダ)のパスを表示します。)
ちなみに、バッククォートを入力する場合、「shift」を押しながら 「@」を押すことで表示されます。
エラー制御演算子とは
エラー制御演算子「@」は、式の前につけることで、エラーメッセージを表示させないようにすることができます。(エラー制御演算子 - Manual)
用途としては、開発途中などで既知のエラーを一時的に非表示にしたい場合などに使用します。
では実際に、定義していない変数「$a」「$b」「$c」の内、「$b」にのみ「@」をつけた状態で表示させてみましょう。
</>php<?php
echo $a;
echo @$b;
echo $c; ?>
定義していない変数を3つ呼び出そうとしているので、「未定義の変数です」というエラーが3つ出るはずが、「$b」にのみエラー制御演算子「@」をつけているので1つ非表示になっていますね。
NULL合体演算子とは
NULL合体演算子「??」は、値がNULLだった場合に、代わりの値を指定することができます。(新機能 - Manual)
値が入っていない変数を使用することで発生するエラーを、未然に防ぐために使用されたりします。
「??」の左辺に「対象の値」を、右辺に、左辺の値が「NULLだった場合の代わりの値や式」を指定します。
では、例として何も定義していない「$_GET['user']」を、「??」を使って判定してみましょう。
</>php<?php
$username = $_GET['user'] ?? '未入力です';
echo $username; ?>
今回は、userを特に指定していないので、代わりに用意した「未入力です」が出力されました。
ちなみに、今回の例文は以下の 三項演算子とisset()を組み合わせたコードを短く記述したものです。
</>php<?php
$username = isset($_GET['user']) ? $_GET['user'] : '未入力です'; ?>
issetは、変数に値がセットされていて、NULLでないときにtrueを返します。
三項演算子の条件式で判定した後、trueの場合は同じ値($_GET['user'])を返し、falseの場合は「未入力です」が返ります。
演算子の優先順位
phpの演算子は全てに優先順位が決められており、1つの式の中に複数の演算子がある場合、PHPは優先順の高い順に演算を行います。
例えば、1+5*3の答えは16であり18とはならないのは、「*」が「+」より高い優先順位だからです。(演算子の優先順位 - Manual)
優先順位
次の表では、優先順位が高い順に演算子を挙げています。 同じ行にある演算子は優先順位が等しくなります。そのような場合は、 結合時の評価にしたがってグループ分けが決まります。
優先順位 | 演算子 | 追加情報 |
---|---|---|
clone new | ||
** | 代数演算子 | |
+ - ++ -- ~ (int) (float) (string) (array) (object) (bool) @ | 代数演算子 (単項の + と -), 加算子/減算子, ビット演算子, 型の相互変換 そして エラー制御演算子 | |
instanceof | 型演算子 | |
! | 論理演算子 | |
* / % | 代数演算子 | |
+ - . | 代数演算子 (単項の + と -), 配列演算子 そして 文字列演算子 (PHP 8.0.0 より前のバージョンの.) | |
<< >> | ビット演算子 | |
. | 文字列演算子 (PHP 8.0.0 以降) | |
< <= > >= | 比較演算子 | |
== != === !== <> <=> | 比較演算子 | |
& | ビット演算子 そして リファレンス | |
^ | ビット演算子 | |
| | ビット演算子 | |
&& | 論理演算子 | |
|| | 論理演算子 | |
?? | NULL合体演算子 | |
? : | 三項演算子 (PHP 8.0.0 より前のバージョンでは、左結合でした) | |
= += -= *= **= /= .= %= &= |= ^= <<= >>= ??= | 代入演算子 | |
and | 論理演算子 | |
xor | 論理演算子 | |
or | 論理演算子 |
結合則
結合則とは、同じ優先順位の演算子が並んでいる場合に処理する順序を決めるルールです。
次の表では、その結合則で演算子を「左から右」または「右から左」の処理するかを記しています。
結合性 | 演算子の種類 | 演算子 |
左結合 | 算術演算子 | * / % + - |
ビット演算子 | << >> & ^ | | |
論理演算子 | && || and xor or | |
条件演算子 | ? : | |
その他 | . instanceof | |
右結合 | 算術演算子 | ** |
論理演算子 | ! | |
代入演算子 | = += -= *= **= /= .= %= &= |= ^= <<= >>= ??= | |
その他 | clone ~ ?? (int) (float) (string) (array) (object) (bool) @ | |
非結合 | 比較演算子 | < <= > >= == != === !== <> <=> |
その他 | new ++ -- |
php8になって変わったこと
- 文字列の連結 「.」 の優先順位は、 代数演算子の加算/減算 ( + および - ) と ビットシフト演算子 ( << および >> ); よりも低くなりました。(これより前のバージョンでは、文字列の連結は + と - と同じ優先順位を持ち、 << と >> よりは高い優先順位を持っていました。)
- 三項演算子 「? : 」 は、 どの演算とも結合しなくなりました。( これより前のバージョンでは、左結合でした。)
最後に
今回はphpの基本である演算子の中でも、よく使用する演算子について解説しました。
もちろんこれ以外にもまだまだ演算子について解説していますので、もっと知りたい方は是非こちらもチェックしてみて下さい。