switch ($value)는 하나의 값을 여러 case 레이블과 비교하고, 처음 일치한 레이블 아래의 코드를 실행합니다. 각 case는 break로 끝나며, 아무것과도 일치하지 않으면 default가 처리합니다.
$day를 'fri', 'sun', 'wed'로 바꿔 다시 실행해 보세요. default가 마지막 case라면 break가 필요 없습니다.
여러 case를 하나의 블록으로
여러 값에 같은 코드를 실행하려면 case 레이블을 사이에 아무것도 없이 겹쳐 쓰세요. 일치한 레이블은 아래의 코드로 이어집니다.
match와 달리 switch에는 case 'jpg', 'jpeg': 같은 쉼표 문법이 없습니다. 레이블을 겹쳐 쓰는 것이 유일한 방법입니다.
폴스루: break가 없으면 일어나는 일
switch를 멈추는 것은 break입니다. 이것이 없으면 PHP는 일치한 case를 실행한 뒤 레이블을 무시하고 아래의 모든 case로 계속 진행하며, break나 끝에 닿아야 멈춥니다.
여기서는 폴스루가 의도된 것입니다. 각 요금제는 자신의 기능에 더해 더 저렴한 요금제의 기능을 모두 받습니다. 일부러 이렇게 쓸 때는 // no break 같은 주석을 달아 다음에 읽는 사람이 "고치지" 않게 하세요. 의도하지 않았다면 빠진 break는 switch에서 가장 흔한 버그 중 하나입니다.
switch는 느슨한 비교(==)를 쓴다
모든 case는 ===가 아니라 ==로 확인됩니다. 숫자 문자열은 숫자와 일치하고, null은 false와 ""에 일치하며, true는 참으로 취급되는 모든 값과 일치합니다. 셀을 눌러 두 연산자를 비교해 보세요.
| $a == $b | 0 | 1 | "0" | "1" | "" | null | false | true | "a" | "10" | "1e1" |
|---|---|---|---|---|---|---|---|---|---|---|---|
| 0 | |||||||||||
| 1 | |||||||||||
| "0" | |||||||||||
| "1" | |||||||||||
| "" | |||||||||||
| null | |||||||||||
| false | |||||||||||
| true | |||||||||||
| "a" | |||||||||||
| "10" | |||||||||||
| "1e1" |
실제로는 이런 결과가 나옵니다. 폼에서 온 입력 문자열 "1"은 변환 없이 case 1:에 들어가며, 대개 원하는 동작입니다. 하지만 비어 있지 않은 문자열과 switch (true)를 함께 쓰거나 null이 case false:를 만나면 예상하지 못한 case가 선택될 수 있습니다.
null 줄을 보세요. null == 0이 이미 참이고 case 0:이 먼저 오기 때문에 case false:까지 가지 않습니다. 느슨한 비교에서는 case의 순서가 결과를 바꿉니다. PHP 8부터 0 == "a"는 거짓이므로(PHP 7에서는 참이었습니다) 숫자가 아닌 문자열은 더 이상 case 0:에 일치하지 않습니다. ===가 필요하다면 이 페이지 끝에서 다루는 match 표현식을 쓰세요.
범위와 조건을 위한 switch(true)
case 레이블에는 어떤 표현식이든 올 수 있습니다. switch (true)에서는 각 case가 조건이 되고, 처음으로 true와 같은 것이 선택됩니다.
모든 case가 진짜 불리언인지 확인하세요. 느슨한 비교 때문에 case $name:은 $name이 비어 있지 않은 문자열이면 언제나 일치합니다.
반복문 안의 switch: break와 continue
반복문 안에서 switch의 break는 반복문이 아니라 switch만 빠져나옵니다. 반복문을 멈추려면 break 2를 쓰세요. switch 안의 continue는 break처럼 동작하며, PHP는 컴파일 시점에 경고합니다: "continue" targeting switch is equivalent to "break". Did you mean to use "continue 2"?. 다음 반복으로 건너뛰려면 continue 2를 쓰세요.
switch와 match
PHP 8은 match를 추가했고, 이것은 switch의 대부분 용도를 더 적은 코드로 처리합니다. ===로 비교하고, 값을 반환하며, 폴스루가 없고, 쉼표로 구분한 조건을 허용하며, 아무것도 일치하지 않으면 UnhandledMatchError를 던지므로 빠뜨린 case가 조용히 넘어갈 수 없습니다.
case 하나에 여러 문장이 필요하거나, 요금제 예제처럼 폴스루 자체가 목적일 때는 switch를 쓰세요. 값을 결과로 매핑할 때는 match가 더 짧고 안전합니다.
자주 묻는 질문
PHP switch에서 여러 case를 하나의 블록으로 묶으려면 어떻게 하나요?
case 레이블을 사이에 코드 없이 겹쳐 쓰세요: case 'sat': case 'sun': echo 'weekend'; break;. 각 레이블이 공통 코드로 이어집니다. switch에는 case 'sat', 'sun': 문법이 없습니다. 쉼표 형태는 match의 문법입니다.
PHP switch는 엄격한 비교를 하나요?
아니요. switch는 느슨한 ==로 비교하므로 case '1':은 정수 1과 일치하고 case 0:은 '0'과 일치합니다. 엄격한 === 비교가 필요하면 match 표현식이나, 각 case 안에서 ===를 쓰는 switch (true)를 사용하세요.
PHP switch에서 break를 빠뜨리면 어떻게 되나요?
실행이 아래로 이어집니다(폴스루). 일치한 case 다음에도 PHP는 break, return 또는 switch의 끝에 도달할 때까지 그 아래 모든 case의 코드를 계속 실행합니다. 의도한 경우도 있지만 대개는 버그입니다.
PHP switch로 '보다 크다' 같은 범위를 확인할 수 있나요?
네, switch (true)를 쓰면 됩니다. 각 case에 case $score >= 90: 같은 조건을 넣으면 처음으로 참인 것이 실행됩니다. match (true) 표현식도 같은 일을 엄격한 비교로 하고 값을 반환합니다.