この内容は古いバージョンです。最新バージョンを表示するには、戻るボタンを押してください。
バージョン:5
ページ更新者:guest
更新日時:2026-06-11 07:10:02

タイトル: 条件分岐
SEOタイトル: PHP 条件分岐完全ガイド (if/switch/match)

この記事の要点
  • PHP の条件分岐は if/elseif/else, switch, match (PHP 8+), 三項演算子, Null合体 の 5 種
  • switch は 緩い比較 (==) → 型まで見たいなら match を使う
  • 三項は短い式向き、ネストすると可読性が一気に落ちる → match や Early Return に逃がす
  • ネストが深くなったら Early Return (Guard Clause) でフラット化
  • 複雑な if-elseif 連鎖は Strategy パターン連想配列の dispatch に置換

if / elseif / else

if ($age >= 20) {
    echo 'adult';
} elseif ($age >= 13) {
    echo 'teen';
} else {
    echo 'child';
}

// 中括弧省略は推奨しない (バグの温床)
if ($x > 0) echo 'pos';   // 動くが避ける

// テンプレート (Blade ではなく素 PHP)
?>
<?php if ($user->isAdmin()): ?>
    <a href="/admin">Admin</a>
<?php elseif ($user->isLoggedIn()): ?>
    <a href="/mypage">My Page</a>
<?php else: ?>
    <a href="/login">Login</a>
<?php endif; ?>
<?php

switch

switch ($status) {
    case 'pending':
    case 'processing':           // fall-through で OR
        echo '進行中';
        break;
    case 'shipped':
        echo '発送済';
        break;
    case 'delivered':
        echo '配達完了';
        break;
    default:
        echo '不明';
}

// ★ 罠1: 緩い比較 (==)
switch ($x) {
    case 0:    echo 'zero'; break;
    case '0':  echo 'str';  break;   // 到達しない (0 == '0')
}

// ★ 罠2: break 忘れ
switch ($x) {
    case 1:
        $y = 'one';
        // break 忘れ → 2 のブロックも実行されてしまう
    case 2:
        $y = 'two';
        break;
}

match 式 (PHP 8+)

// 戻り値を持つ「式」
$label = match ($status) {
    1, 2 => '進行中',           // OR
    3    => '発送済',
    4    => '配達完了',
    default => '不明',
};

// 厳密比較 (===)
$x = match (0) {
    '0' => 'str',
    0   => 'int',     // ← ここに当たる
};

// 該当なし (default なし) → UnhandledMatchError
try {
    $r = match (99) {
        1 => 'a',
        2 => 'b',
    };
} catch (\UnhandledMatchError $e) {
    // 全パターン網羅漏れを実行時に検出できる
}

// 真偽条件のディスパッチ
$cat = match (true) {
    $age < 13 => 'child',
    $age < 20 => 'teen',
    default   => 'adult',
};

switch vs match 比較表

項目switchmatch (PHP 8+)
比較== (緩い)=== (厳密)
break必要 (忘れバグ)不要
戻り値なし (文)あり (式)
網羅性抜け落ち放置UnhandledMatchError
複文OK1 式のみ (匿名関数で回避可)
fall-throughありなし (OR は 1, 2 =>)

三項演算子

$label = $age >= 20 ? 'adult' : 'minor';

// Elvis (PHP 5.3+)
$name = $input ?: 'Guest';

// Null 合体
$name = $input ?? 'Guest';

// ❌ ネスト三項は禁止 (PHP 8+ は括弧必須)
$cat = $age < 13 ? 'child' : ($age < 20 ? 'teen' : 'adult');
// → match の方が読みやすい
$cat = match (true) {
    $age < 13 => 'child',
    $age < 20 => 'teen',
    default   => 'adult',
};

Early Return でネストを潰す

// ❌ ネスト地獄
function process(?User $user): string {
    if ($user !== null) {
        if ($user->isActive()) {
            if ($user->hasPermission('edit')) {
                return doEdit($user);
            } else {
                return 'no permission';
            }
        } else {
            return 'inactive';
        }
    } else {
        return 'no user';
    }
}

// ✅ Early Return でフラット
function process(?User $user): string {
    if ($user === null)              return 'no user';
    if (!$user->isActive())          return 'inactive';
    if (!$user->hasPermission('edit')) return 'no permission';
    return doEdit($user);
}

Strategy パターンで if 連鎖を消す

// ❌ どんどん増える if-elseif
function calcShipping(string $method, float $weight): int {
    if ($method === 'yamato') {
        return $weight * 100 + 500;
    } elseif ($method === 'sagawa') {
        return $weight * 90 + 600;
    } elseif ($method === 'japan_post') {
        return $weight * 80 + 400;
    }
    throw new InvalidArgumentException();
}

// ✅ 連想配列ディスパッチ
$strategies = [
    'yamato'     => fn($w) => $w * 100 + 500,
    'sagawa'     => fn($w) => $w * 90  + 600,
    'japan_post' => fn($w) => $w * 80  + 400,
];

function calcShipping(string $m, float $w) use ($strategies): int {
    $fn = $strategies[$m] ?? throw new InvalidArgumentException();
    return $fn($w);
}

isset / empty / null 合体の使い分け

// 入力値の有無
if (isset($_POST['name'])) { /* 設定済 (null以外) */ }
if (!empty($_POST['name'])) { /* truthy */ }   // ⚠ 0 / "0" / "" も false
$name = $_POST['name'] ?? '';                  // null → ''

// PHP 7+: 短く書ける
$user = User::find($id) ?? throw new NotFoundException();   // PHP 8+

FAQ

Q: if と switch、どちらを使うべき?
A: 同じ変数を多数の値と比較するなら switch / match、複数条件を組合せるなら if。PHP 8 以降は match を第一候補に。

Q: elseifelse if の違い
A: ほぼ同じだが、テンプレート構文 (endif) では elseif でないと動かない。常に elseif 推奨。

Q: ネストした条件分岐をリファクタしたい
A: 順に Early Return → 連想配列ディスパッチ → Strategy パターン → State パターン と検討。