filter_var($value, FILTER_VALIDATE_EMAIL)은 값이 유효한 이메일 주소면 그 값을, 아니면 false를 반환합니다. 다른 형식을 확인하려면 필터를 바꾸세요: FILTER_VALIDATE_INT, FILTER_VALIDATE_FLOAT, FILTER_VALIDATE_URL, FILTER_VALIDATE_BOOL, FILTER_VALIDATE_IP. 결과는 항상 === false와 비교하세요.
두 결과가 사람들을 놀라게 합니다. ada@example은 도메인에 점이 없어서 거부되고, ' ada@example.com'은 앞의 공백 때문에 거부되므로 검증 전에 입력을 trim()하세요.
폼에서 받은 이메일 검증하기
같은 확인을 폼 뒤에 둔 것입니다. 실행하고 주소를 입력한 뒤 Check를 누르세요. 입력이 $_POST에 담긴 채로 블록이 다시 실행됩니다.
FILTER_VALIDATE_EMAIL은 형식만 확인합니다. nobody@example.com도 통과하고, 도메인에 오타가 있는 주소도 통과할 것입니다. ASCII가 아닌 문자는 거부됩니다. adä@example.com은 @ 앞에 그런 문자를 허용하는 FILTER_FLAG_EMAIL_UNICODE와 함께일 때만 통과하고, exämple.com 같은 도메인은 먼저 xn-- 형태로 바꾸지 않으면 플래그가 있어도 실패합니다. 주소가 동작하는지 아는 유일한 방법은 확인 링크를 보내는 것입니다.
min_range, max_range로 정수 검증하기
FILTER_VALIDATE_INT는 유효한 문자열을 int로 바꾸고 나머지는 모두 거부합니다. 옵션 배열은 범위와 기본값을 추가합니다.
앞뒤 공백과 앞의 +는 받아들이고, 앞의 0('042')은 받아들이지 않으며, '42'에 대한 결과는 문자열이 아니라 정수 42입니다. 범위를 벗어나면 false이고, default 옵션이 있으면 false 대신 기본값을 받으며, ?page= 같은 것에 편리합니다(_POST 참고). 0x1A나 0755를 받아들이려면 FILTER_FLAG_ALLOW_HEX나 FILTER_FLAG_ALLOW_OCTAL을 추가하세요.
0과 false의 함정
유효한 '0'은 정수 0을 반환하고, 0은 거짓으로 취급됩니다. 단순한 if는 이를 실패로 취급합니다.
FILTER_VALIDATE_FLOAT('0.0')과 false가 유효한 답인 FILTER_VALIDATE_BOOL에도 같은 일이 적용됩니다. FILTER_NULL_ON_FAILURE가 그것을 위한 것입니다.
불리언, 실수, URL, IP 주소
FILTER_VALIDATE_BOOL은 PHP 8의 이름이고, FILTER_VALIDATE_BOOLEAN은 같은 필터입니다. FILTER_NULL_ON_FAILURE가 없으면 'maybe'는 'off'와 구별할 수 없는 false를 반환합니다.
유효한 URL이 안전한 링크는 아니다
FILTER_VALIDATE_URL은 문자열이 어떤 스킴이든 URL 모양인지 확인합니다. 여기에는 href에 절대 넣고 싶지 않은 스킴도 포함됩니다.
javascript://comment%0Aalert(1)은 FILTER_VALIDATE_URL을 통과하고, %0A가 //comment를 끝내기 때문에 링크를 클릭하면 브라우저가 JavaScript로 실행합니다. 사용자의 URL을 페이지에 출력하기 전에 parse_url()로 스킴을 확인하세요. FILTER_FLAG_PATH_REQUIRED와 FILTER_FLAG_QUERY_REQUIRED로 특정 부분을 요구할 수도 있습니다.
sanitize 필터
sanitize 필터는 예, 아니요를 말하는 대신 문자를 제거합니다. 입력을 정규화하는 데는 유용하지만 출력해도 안전하게 만들지는 않습니다.
첫 줄을 보세요. Order #12-345 (x2)가 입력에 없던 숫자 12-3452가 되고, 세 번째 줄은 아무도 입력하지 않은 주소입니다. sanitize를 한다면 그 결과를 나중에 검증하세요. HTML에 출력하는 모든 것에는 출력 시점의 htmlspecialchars()가 맞는 도구입니다(FILTER_SANITIZE_FULL_SPECIAL_CHARS도 같은 이스케이프를 합니다). FILTER_SANITIZE_STRING은 PHP 8.1부터 폐지 예정이며, 대신 무엇을 쓸지는 htmlspecialchars를 참고하세요.
filter_var_array로 폼 전체 검증하기
filter_var_array()는 키마다 필터 하나를 적용하고, 요청한 모든 키가 담긴 배열을 반환합니다. 필터링된 값, 검증에 실패하면 false, 키가 없으면 null입니다.
role은 사라졌습니다. 나열하지 않은 키는 버려지므로 방문자가 폼에 role=admin을 추가해 저장되게 하는 일을 막습니다. country는 전송되지 않았으므로 null입니다. 웹 서버에서는 filter_input_array(INPUT_POST, $rules)가 요청에서 바로 읽으며 같은 일을 합니다.
자주 묻는 질문
PHP에서 이메일 주소를 검증하려면 어떻게 하나요?
filter_var($email, FILTER_VALIDATE_EMAIL)을 쓰세요. 유효하면 이메일 문자열을, 아니면 false를 반환합니다: if (filter_var($email, FILTER_VALIDATE_EMAIL) === false) { /* invalid */ }. 형식만 확인하며, 주소가 실제로 있는지 알려면 확인 이메일을 보내세요.
PHP에서 문자열이 정수인지 확인하려면 어떻게 하나요?
filter_var($s, FILTER_VALIDATE_INT)는 "42", "-7", " 42 "에 대해 int를 반환하고, "4.2", "42abc", "042"에 대해 false를 반환합니다. 유효한 "0"은 거짓으로 취급되는 0을 반환하므로 !== false로 비교하세요.
filter_var가 0에 대해 false를 반환하는 이유는 무엇인가요?
그렇지 않습니다. filter_var('0', FILTER_VALIDATE_INT)는 정수 0을 반환합니다. 버그는 0을 false처럼 취급하는 확인 if (filter_var(...))에 있습니다. if (filter_var($v, FILTER_VALIDATE_INT) !== false)로 쓰세요.
PHP 8.1에서 FILTER_SANITIZE_STRING을 대체한 것은 무엇인가요?
직접적인 대체는 없습니다. 이름이 주지 않는 안전을 약속했기 때문에 폐지 예정이 되었습니다. 기대하는 입력을 검증하고, 그대로 저장하고, 출력할 때 htmlspecialchars()로 이스케이프하세요. 태그를 제거해야 한다면 strip_tags()를 쓰세요.
filter_var와 filter_input의 차이는 무엇인가요?
filter_var()는 넘긴 어떤 값이든 필터링합니다. filter_input(INPUT_GET, 'id', FILTER_VALIDATE_INT)는 원래 요청에서 바로 읽으므로, 파라미터가 없으면 null을 반환하고 코드가 $_GET에 가한 변경을 무시합니다. 둘 다 같은 필터와 옵션을 받습니다.