タイトル: 演算子
SEOタイトル: PHP 演算子完全リファレンス
| この記事の要点 |
|
演算子カテゴリ一覧
| カテゴリ | 記号 | 用途 |
|---|---|---|
| 算術 | + - * / % ** | 四則演算 / 剰余 / 累乗 |
| 代入 | = += -= *= /= %= .= **= ??= | 値の代入と複合代入 |
| 比較 | == === != !== < > <= >= <=> | 等値 / 大小 / Spaceship |
| 論理 | && || ! and or xor | 真偽値の組み合わせ |
| ビット | & | ^ ~ << >> | 整数のビット演算 |
| 文字列 | . .= | 連結 |
| 配列 | + == === != !== | 和集合 / 等値 |
| 型 | instanceof | クラス判定 |
| Null 合体 | ?? ??= | null のときの代替値 |
| Spread | ... | 配列展開 / 可変長引数 |
| 三項 | ? : ?: | 条件式 / Elvis |
| Match (PHP 8+) | match | switch の式バージョン |
算術演算子
$a = 10; $b = 3;
echo $a + $b; // 13
echo $a - $b; // 7
echo $a * $b; // 30
echo $a / $b; // 3.3333333333333
echo $a % $b; // 1 (剰余)
echo $a ** $b; // 1000 (累乗 PHP 5.6+)
// 整数除算は intdiv
echo intdiv(10, 3); // 3
// インクリメント / デクリメント
$i = 5;
$i++; // 6 (後置)
++$i; // 7 (前置)
$i--; // 6
代入演算子
$x = 10;
$x += 5; // $x = $x + 5 → 15
$x -= 3; // 12
$x *= 2; // 24
$x /= 4; // 6
$x %= 4; // 2
$x **= 3; // 8
$s = 'Hello';
$s .= ' World'; // 'Hello World'
// Null 合体代入 (PHP 7.4+)
$config['timeout'] ??= 30; // 未設定 or null のときだけ代入
// 参照代入
$a = 1;
$b = &$a;
$b = 99; // $a も 99
比較演算子 (== vs === の罠)
// 緩い比較 (==) は型変換が入り事故る
var_dump(0 == 'abc'); // PHP 7: true / PHP 8: false (仕様変更)
var_dump('1' == '01'); // true (両方数値扱い)
var_dump('10' == '1e1'); // true (10 == 10)
var_dump(100 == '1e2'); // true
var_dump(null == false); // true
var_dump(null == 0); // true
var_dump([] == false); // true
// 厳密比較 (===) なら型まで一致
var_dump(0 === 'abc'); // false
var_dump('1' === 1); // false
// Spaceship 演算子 (PHP 7+): -1 / 0 / 1
echo 1 <=> 2; // -1
echo 1 <=> 1; // 0
echo 2 <=> 1; // 1
// usort と組み合わせて簡潔に
usort($users, fn($a, $b) => $a->age <=> $b->age);
論理演算子
// && と and の違いは「優先順位」
$a = true && false; // $a = false
$a = true and false; // $a = true ! (= が先に評価される)
// → 常に && / || を使う
// 短絡評価
$user && $user->isAdmin(); // $user が falsy なら右辺評価しない
// XOR
var_dump(true xor false); // true
var_dump(true xor true); // false
ビット演算子
// フラグ管理に便利
const READ = 1 << 0; // 1
const WRITE = 1 << 1; // 2
const EXECUTE = 1 << 2; // 4
$perm = READ | WRITE; // 3
$hasRead = $perm & READ; // 1 (true)
$perm ^= WRITE; // WRITE を反転
$perm &= ~READ; // READ を OFF
echo PHP_INT_SIZE; // 8 (64bit)
echo 1 << 63; // -9223372036854775808 (オーバーフロー)
Null Coalescing (??) と Nullsafe (?->)
// PHP 7+: ??
$name = $_GET['name'] ?? 'Guest';
// = isset($_GET['name']) ? $_GET['name'] : 'Guest'
// 連鎖もOK
$config = $userConfig ?? $appConfig ?? $defaultConfig;
// PHP 7.4+: ??=
$config['debug'] ??= false;
// PHP 8+: Nullsafe ?->
$country = $user?->getAddress()?->getCountry()?->getName();
// 途中で null なら全体 null。例外にならない
// 短絡なので副作用なし
$user?->logAccess(); // $user が null なら呼ばない
三項演算子と Elvis
// 通常の三項
$status = $age >= 20 ? 'adult' : 'minor';
// Elvis (省略形 PHP 5.3+)
$name = $input ?: 'Unknown';
// = $input ? $input : 'Unknown'
// 違い: ?? は null だけ、?: は falsy 全部 (0 / '' / [] も含む)
$a = '0';
echo $a ?? 'default'; // '0' (?? は null 以外通す)
echo $a ?: 'default'; // 'default' ('0' は falsy)
// PHP 8 から三項演算子の連鎖はエラー
// $a ? $b : $c ? $d : $e → 括弧必須
Match 式 (PHP 8+)
// switch との違い
// 1. 厳密比較 (===)
// 2. 戻り値を持つ式
// 3. break 不要 (fall-through なし)
// 4. 該当なしで UnhandledMatchError
$label = match ($status) {
1, 2 => 'pending', // OR 条件
3 => 'shipped',
4 => 'delivered',
default => 'unknown',
};
// 条件式 match (PHP 8.0+)
$category = match (true) {
$age < 13 => 'child',
$age < 20 => 'teen',
$age < 65 => 'adult',
default => 'senior',
};
Spread / 可変長引数 (...)
// 配列展開
$a = [1, 2, 3];
$b = [0, ...$a, 4]; // [0, 1, 2, 3, 4]
// PHP 8.1+: 文字列キー対応
$base = ['name' => 'taro'];
$user = [...$base, 'age' => 20];
// 可変長引数
function sum(int ...$nums): int {
return array_sum($nums);
}
sum(1, 2, 3); // 6
sum(...[1, 2, 3]); // 6 (展開して渡す)
優先順位 (主要なもの)
覚えるよりも括弧で明示するのが安全です。よくある事故:
// 代入は && より弱い → 期待通り
$result = $a && $b; // ($a && $b) を $result に
// しかし and は = より弱い → 罠
$result = true and false;
// = ($result = true) and false
// → $result は true !
// → 常に && を使うこと
// 三項より代入の方が弱い
$x = $a > 0 ? 'pos' : 'neg'; // OK
// 連結 . は + より強い (PHP 8 から逆転 → エラー回避)
echo 1 + 2 . 3 + 4; // PHP 8 では deprecation警告
// → echo (1 + 2) . (3 + 4); と書く
FAQ
Q: == と === どっちを使うべき?
A: 原則 ===。== は型変換が入り PHP 8 で挙動が変わったケースもあり、意図しないバグの温床です。
Q: ?? と ?: の使い分けは?
A: ?? は「null だったら」専用。?: は「falsy だったら」(0 / 空文字も含む)。フォーム入力で 0 を有効値として扱うときは ?? 必須。
Q: Match と switch どちらを使うべき?
A: 新規コードは Match 推奨。型安全 (===)、戻り値、break 忘れバグなし、全パターン網羅の保証 (UnhandledMatchError) が利点。