PHP 문자열은 바이트 시퀀스 일 뿐이며 어떤 태그에도 인코딩이 없습니다. 문자열 값은 클라이언트 (HTTP를 통한), 데이터베이스, 파일 또는 소스 코드의 문자열 리터럴 등 다양한 소스에서 제공 될 수 있습니다. PHP는이 모든 것을 바이트 시퀀스로 읽으며 인코딩 정보를 추출하지 않습니다.
모든 데이터 소스와 대상이 동일한 인코딩을 사용하는 한 PHP에서 문자가 아닌 바이트 수를 계산하므로 문자열 위치가 잘못되어 멀티 바이트 인코딩을 사용하는 경우가 발생할 수 있습니다.
그러나 인코딩이 일치하지 않으면 (예 : UTF-8로 저장된 소스 파일에 문자열 리터럴을 작성한 다음 Latin-1이 필요한 데이터베이스로 전송) PHP는 변환을 수행하지 않습니다. 행복하게 바이트를 원시로 복사하십시오.
가장 순수한 해결책은 다음과 같습니다.
- PHP의 내부 인코딩을 UTF-8로 설정하십시오.
- 모든 소스 파일을 UTF-8로 저장하십시오.
- UTF-8을 출력 인코딩으로 사용하십시오 (적절한
Content-type
헤더 를 보내는 것을 잊지 마십시오 ).
- UTF-8을 사용하도록 데이터베이스 연결을 설정하십시오 (
SET NAMES UTF8
MySQL에서).
- 가능하면 다른 모든 것을 UTF-8로 구성하십시오.
- 제어 할 수없는 항목 (예 : 타사 웹 서비스)의 경우 인코딩을 알고 가능한 빨리 UTF-8로 변환 한 다음 가능한 한 늦게 다른 인코딩으로 다시 변환하십시오.
왜 UTF-8입니까? 모든 유니 코드 문자를 나타낼 수 있으므로 기존의 모든 7 비트 및 8 비트 인코딩을 대체하고 ASCII와 이진 호환 가능하므로 모든 유효한 ASCII 문자열도 유효한 UTF-8 문자열입니다 (단, vv는 아님) ).
귀하의 예에서 이런 일이 발생합니다.
먼저 소스 파일을 저장합니다. 텍스트 편집기는 아마도 UTF-8을 사용하도록 구성되어 있으므로 문자열 리터럴은 디스크에서 UTF-8로 인코딩됩니다. PHP는이 파일을 읽고 문자열을 일련의 바이트로 해석합니다. $original
이제 7 바이트의 UTF-8로 인코딩 된 문자열을 보유하는데, 이는 바이트 순서 일뿐입니다 (각 문자는 2 바이트 이상으로 표시되므로 7 바이트 이상을 포함하지만). 그런 다음을 호출 echo $original
하면 인코딩 된 문자열이 그대로 클라이언트로 전송됩니다. 클라이언트에게 UTF-8을 요구하라고 말하면 모든 것이 정상이지만, 그렇지 않은 경우 PHP는 차이점을 알 수있는 방법이 없으므로 브라우저에서 쓰레기가 발생합니다. 실험으로 다음을 시도하십시오.
$original = "शक्नोम्यत्तुम्";
echo strlen($original);
strlen
는 인코딩에 구애받지 않으며 고정 너비 8 비트 인코딩, 즉 문자 당 1 바이트를 가정하므로 문자가 아닌 바이트를 계산합니다.