# ch04 — 論理演算子

Source: https://php-school.pages.dev/topics/conditional/ch04-logical/
Site: AIと学ぶPHPの学校 (https://php-school.pages.dev)
Lesson: 条件分岐
Level: L2

Reference (official): https://www.php.net/manual/ja/language.control-structures.php

## 本文

# ch04 — 論理演算子

## 概要

実際の条件は「年齢が 18 以上 **かつ** 会員登録済み」のように、複数の真偽値を組み合わせて判定したい場面がほとんど。これを表現するのが論理演算子で、`&&` (and: 両方が真) / `||` (or: どちらかが真) / `!` (not: 真偽を反転) の 3 つを覚える。比較演算子で作った `$age >= 18` のような小さな条件を、論理演算子で接着して大きな条件を組み立てるイメージ。

論理演算子のもう 1 つの重要な性質が **短絡評価 (short-circuit)** だ。`A && B` は **A が偽の時点で結果が偽に確定する** ので、PHP は B を評価しない。同じく `A || B` は A が真の時点で B は評価されない。これを利用して、`if ($user !== null && $user->isAdmin())` のように「左でガードしてから右で本処理」と書くと、null 参照エラーを避けられる。逆に「右側に副作用があるコード」を書くと、左の結果次第で実行されたりされなかったりして、思わぬバグになる。

PHP には `&&` `||` の他に **キーワード版** の `and` `or` も存在する。一見同じに見えるが、`&&` と `and` は **演算子の優先順位が違う**。たとえば `$a = true && false` は `$a` が `false` になるが、`$a = true and false` は `$a` が `true` になる (`=` より `and` が弱いため代入が先)。歴史的事情で残っているが、現代のコードでは混乱を避けるため `&&` `||` を使うのが鉄則だ。

## 学習目標

- `&&` (and) で「両方が真」を判定できる
- `||` (or) で「どちらかが真」を判定できる
- `!` (not) で真偽を反転できる

## 所要時間

スライド 4 分 + ドリル 3 問 = **15 分**

## ドリル

| no | 内容 |
|---|---|
| 01 | `&&` で「0 以上 かつ 100 以下」を判定 |
| 02 | `\|\|` で「Sat または Sun」を判定 |
| 03 | `!` で「偶数ではない」を判定 |

## 採点

```bash
php scripts/grade.php topics/conditional/ch04-logical/drill/01-range/
```

## 関連チャプター

- [`ch03-comparison`](../ch03-comparison/) — 論理演算子で繋ぐ前の小さな条件式
- [`ch02-if-else`](../ch02-if-else/) — 複合条件を `if / else` で分岐させる
- [`ch05-switch`](../ch05-switch/) — 値の多分岐に特化した別構文

## スライド

---
marp: true
theme: dojo
paginate: true
size: 16:9
---

<!--
LLM_CONTEXT:
  Lesson 2 / Chapter 4
  目的: && / || / ! を使って複数条件を 1 つの if にまとめられるようにする
  扱わない: 短絡評価の副作用 / xor / ビット演算 (& | ^)
  読み上げ時間目安: 4 分
-->

# 論理演算子

Lesson 2 / Chapter 4

---

## 複数の条件を組み合わせたい

「年齢が 18 以上 **かつ** 65 未満」のように、
**条件を 2 つ以上つなげて判定したい** ことがある。

これまでの書き方:

```php
<?php
if ($age >= 18) {
    if ($age < 65) {
        echo "現役世代\n";
    }
}
```

if を 2 段ネストすると読みにくい。論理演算子で 1 つにまとめる。

---

## `&&` (かつ・and)

```php
<?php
if ($age >= 18 && $age < 65) {
    echo "現役世代\n";
}
```

- `A && B` は **両方が真のときだけ** 真
- 「**かつ**」「**両方**」を表現したいときに使う

| A | B | A && B |
|---|---|---|
| 真 | 真 | 真 |
| 真 | 偽 | 偽 |
| 偽 | 真 | 偽 |
| 偽 | 偽 | 偽 |

---

## `||` (または・or)

```php
<?php
if ($day === "Sat" || $day === "Sun") {
    echo "週末\n";
}
```

- `A || B` は **どちらかが真なら** 真
- 「**または**」「**どっちか**」を表現したいときに使う

| A | B | A \|\| B |
|---|---|---|
| 真 | 真 | 真 |
| 真 | 偽 | 真 |
| 偽 | 真 | 真 |
| 偽 | 偽 | 偽 |

---

## `!` (ではない・not)

```php
<?php
if (!($n % 2 === 0)) {
    echo "偶数ではない\n";
}
```

- `!A` は **A の真偽を反転** する
- 「**〜ではない**」を表現したいときに使う
- 真 → 偽、偽 → 真

`($n % 2 === 0)` が「偶数」を表すので、
`!($n % 2 === 0)` で「偶数ではない」になる。

---

## 組み合わせの例

```php
<?php
if ($n >= 0 && $n <= 100) {
    echo "範囲内\n";
}
```

- 「0 以上 **かつ** 100 以下」= 範囲チェックの定番
- `&&` の左右はそれぞれ独立した条件式

```php
<?php
if (!($age >= 18 && $age < 65)) {
    echo "現役世代ではない\n";
}
```

`!(...)` でまとめて反転もできる。

---

## このチャプターでできるようになること

✅ `&&` で「両方が真」を判定できる
✅ `||` で「どちらかが真」を判定できる
✅ `!` で真偽を反転できる
✅ 複数条件を 1 つの if にまとめられる

→ ドリルへ
