[php] UTF-8

새 서버를 설정하고 있으며 웹 응용 프로그램에서 UTF-8을 완전히 지원하려고합니다. 나는 과거에 기존 서버에서 이것을 시도했으며 항상 ISO-8859-1로 돌아 가야하는 것처럼 보입니다.

인코딩 / 문자 세트를 정확히 어디에 설정해야합니까? 이를 위해 Apache, MySQL 및 PHP를 구성해야한다는 것을 알고 있습니다. 따라야 할 표준 체크리스트가 있습니까?

MySQL 5, PHP, 5 및 Apache 2를 실행하는 새로운 Linux 서버용입니다.



답변

데이터 저장 :

  • utf8mb4데이터베이스의 모든 테이블 및 텍스트 열에 문자 세트를 지정하십시오 . 따라서 MySQL은 기본적으로 UTF-8로 인코딩 된 값을 실제로 저장하고 검색합니다. 데이터 정렬이 명시 적 문자 세트없이 지정된 utf8mb4경우 MySQL은 암시 적으로 인코딩을 사용 utf8mb4_*합니다.

  • 이전 버전의 MySQL (<5.5.3)에서는 불행히도 간단히 utf8유니 코드 문자의 하위 집합 만 지원하는 간단하게 사용해야 합니다. 농담하길 바래

데이터 액세스 :

  • 애플리케이션 코드 (예 : PHP)에서 사용하는 DB 액세스 방법에 관계없이 연결 문자셋을로 설정해야합니다 utf8mb4. 이런 식으로 MySQL은 데이터를 응용 프로그램으로 전달하거나 그 반대로 전달할 때 기본 UTF-8에서 변환하지 않습니다.

  • 일부 드라이버는 자체 내부 상태를 업데이트하고 연결에 사용될 인코딩을 MySQL에 알리는 연결 문자 세트 구성을위한 고유 한 메커니즘을 제공합니다. 이는 일반적으로 선호되는 방식입니다. PHP에서 :

    • 당신이 사용하는 경우 PDO의 PHP ≥ 5.3.6와 추상화 계층을 지정할 수 있습니다 charset에서 DSN :

      $dbh = new PDO('mysql:charset=utf8mb4');
    • mysqli를 사용하는 경우 다음 을 호출 할 수 있습니다 set_charset().

      $mysqli->set_charset('utf8mb4');       // object oriented style
      mysqli_set_charset($link, 'utf8mb4');  // procedural style
      
    • 일반 mysql 이 붙어 있지만 PHP ≥ 5.2.3을 실행하는 경우을 호출 할 수 있습니다 mysql_set_charset.

  • 드라이버가 연결 문자 세트를 설정하기위한 자체 메커니즘을 제공하지 않는 경우, 애플리케이션이 연결의 데이터가 인코딩 될 것으로 예상하는 방법을 MySQL에 알리기 위해 쿼리를 발행해야 할 수 있습니다 SET NAMES 'utf8mb4'.

  • 위와 마찬가지로 utf8mb4/ 에 관한 동일한 고려 사항이 utf8적용됩니다.

출력 :

  • 응용 프로그램이 텍스트를 다른 시스템으로 전송하는 경우 문자 인코딩에 대해서도 알려야합니다. 웹 애플리케이션을 사용하면 브라우저에 HTTP 응답 헤더 또는 HTML 메타 데이터를 통해 데이터가 전송되는 인코딩을 알려야합니다 .

  • PHP에서는 default_charsetphp.ini 옵션을 사용 하거나 직접 Content-TypeMIME 헤더를 직접 발행 할 수 있습니다. 이는 더 많은 작업이지만 효과는 동일합니다.

  • 를 사용하여 출력을 인코딩 할 때 두 번째 매개 변수로 json_encode()추가하십시오 JSON_UNESCAPED_UNICODE.

입력 :

  • 불행히도, 수신 한 모든 문자열을 저장하거나 다른 곳에서 사용하기 전에 유효한 UTF-8인지 확인해야합니다. PHP mb_check_encoding()는 트릭을 수행하지만 종교적으로 사용해야합니다. 악의적 인 클라이언트가 원하는 인코딩으로 데이터를 제출할 수 있기 때문에이 문제를 해결할 방법이 없습니다. PHP가이 작업을 확실하게 수행 할 수있는 방법을 찾지 못했습니다.

  • 현재 HTML 사양을 읽었을 때 다음 하위 글 머리 기호는 더 이상 최신 HTML에 필요하지 않거나 더 이상 유효하지 않습니다. 브라우저가 문서에 지정된 문자 세트로 작업하고 데이터를 제출한다는 것을 이해합니다. 그러나 이전 버전의 HTML (XHTML, HTML4 등)을 타겟팅하는 경우 다음 사항이 여전히 유용 할 수 있습니다.

    • HTML5 이전의 HTML 전용 : 브라우저에서 전송 한 모든 데이터를 UTF-8로 만들려고합니다. 안타깝게도 확실하게이 작업을 수행 할 수있는 유일한 방법은 accept-charset모든 <form>태그에 속성을 추가하는 것 <form ... accept-charset="UTF-8">입니다.
    • HTML5 이전의 HTML 만 해당 : W3C HTML 사양에 따르면 클라이언트는 서버가 제공 한 모든 문자 집합에서 서버로 양식을 다시 보내도록 기본적으로 설정해야하지만 이는 권장 사항 일 뿐이므로 모든 단일 항목에 대해 명시 적이어야 할 필요가 있습니다. <form>꼬리표.

다른 코드 고려 사항 :

  • 분명히 제공 할 모든 파일 (PHP, HTML, JavaScript 등)은 유효한 UTF-8로 인코딩되어야합니다.

  • UTF-8 문자열을 처리 할 때마다 안전하게 처리해야합니다. 불행히도 어려운 부분입니다. PHP mbstring확장 을 광범위하게 사용하고 싶을 것입니다 .

  • PHP의 내장 문자열 연산은 기본적으로 UTF-8 안전 하지 않습니다 . 연결과 같은 일반적인 PHP 문자열 작업으로 안전하게 할 수있는 것이 있지만 대부분의 경우 동등한 mbstring기능을 사용해야합니다 .

  • 무엇을하고 있는지 (읽기 : 엉망으로 만들지 않기) 위해서는 UTF-8과 그것이 가능한 최저 수준에서 어떻게 작동하는지 알아야합니다. utf8.com 의 링크를 확인 하여 알아야 할 모든 것을 배울 수있는 유용한 자료를 찾아보십시오.


답변

chazomaticus의 훌륭한 답변에 한 가지를 추가하고 싶습니다 .

META 태그를 잊지 마십시오 (예 : HTML4 또는 XHTML 버전 ).

<meta charset="utf-8">

그것은 사소한 것처럼 보이지만 IE7은 전에 그 문제를 겪었습니다.

나는 모든 일을 올바르게하고있었습니다. 데이터베이스, 데이터베이스 연결 및 Content-Type HTTP 헤더는 모두 UTF-8로 설정되었으며 다른 모든 브라우저에서 제대로 작동했지만 Internet Explorer는 여전히 “서유럽 어”인코딩 사용을 주장했습니다.

페이지에 META 태그가 누락되었습니다. 그것을 추가하면 문제가 해결되었습니다.

편집하다:

W3C는 실제로 I18N 전용 의 상당히 큰 섹션을 가지고 있습니다. HTTP, (X) HTML 및 CSS 측면을 설명하는이 문제와 관련된 많은 기사가 있습니다.

HTTP 헤더와 HTML 메타 태그 (또는 XHTML이 XML로 제공되는 경우 XML 선언)를 모두 사용하는 것이 좋습니다.


답변

default_charsetphp.ini에서 설정 하는 것 외에도 header()출력 전에 코드 내에서 올바른 문자 세트를 보낼 수 있습니다 .

header('Content-Type: text/html; charset=utf-8');

대부분의 문자열 함수가 유니 코드에서 작동하지 않으며 일부는 문자열을 완전히 엉망 으로 만들 수 있다는 점을 알고 있다면 PHP에서 유니 코드로 작업하는 것은 쉽습니다 . PHP는 “문자”가 1 바이트 길이 인 것으로 간주합니다. 때때로 이것은 괜찮습니다 (예를 들어 explode()바이트 시퀀스 만 찾아서 구분자로 사용하기 때문에 실제 문자를 찾는 것이 중요하지 않습니다). 그러나 다른 경우에, 함수가 실제로 문자 에서 작동하도록 설계되었을 때 , PHP는 텍스트에 유니 코드로 찾은 멀티 바이트 문자가 있다는 것을 알지 못합니다.

체크인하기에 좋은 라이브러리는 phputf8 입니다. 이것은 모든 “나쁜”기능을 다시 작성하므로 UTF8 문자열에서 안전하게 작업 할 수 있습니다. mbstring 확장과 같은 확장 프로그램 도이 작업을 시도하지만 더 이식성이 있기 때문에 라이브러리를 사용하는 것이 좋습니다 (그러나 대량 시장 제품을 작성하므로 나에게 중요합니다). 그러나 phputf8은 어쨌든 mbstring을 사용하여 성능을 향상시킬 수 있습니다.


답변

PDO를 사용하는 사람과 문제가 있음을 발견했으며 PDO 연결 문자열에이를 사용했습니다.

$pdo = new PDO(
    'mysql:host=mysql.example.com;dbname=example_db',
    "username",
    "password",
    array(PDO::MYSQL_ATTR_INIT_COMMAND => "SET NAMES utf8"));

내가 가져온 사이트는 다운되었지만 운 좋게도 Google 캐시를 사용하여 얻을 수있었습니다.


답변

제 경우 mb_split에는 정규 표현식을 사용하는을 사용했습니다. 따라서 수동으로 정규식 인코딩이 utf-8인지 확인해야했습니다.mb_regex_encoding('UTF-8');

부수적으로 mb_internal_encoding()내부 인코딩이 utf-8이 아니라는 것을 실행 하여 발견 했으며을 실행하여 변경했습니다 mb_internal_encoding("UTF-8");.


답변

우선 <5.3PHP 인 경우 아니요. 해결해야 할 수많은 문제가 있습니다.

unicode , graphemes , string operation , localization 등 을 잘 지원 하는 intl 라이브러리 를 언급 한 사람이 아무도 없습니다 . 아래를 참조하십시오.

PHPBenelux’14 에서 Elizabeth Smith의 슬라이드통해 PHP에서 유니 코드 지원에 대한 정보를 인용 하겠습니다.

국제

좋은:

  • ICU 라이브러리를 감싸는 래퍼
  • 표준화 된 로캘, 스크립트 당 로캘 설정
  • 숫자 서식
  • 통화 형식
  • 메시지 형식 (gettext를 대체 함)
  • 달력, 날짜, 시간대 및 시간
  • 음역
  • 위장 검사기
  • 리소스 번들
  • 변환기
  • IDN 지원
  • 그래 핀
  • 대조
  • 반복자

나쁜:

  • zend_multibite를 지원하지 않습니다
  • HTTP 입력 출력 변환을 지원하지 않습니다
  • 기능 과부하를 지원하지 않습니다

mb_string

  • zend_multibyte 지원 가능
  • 투명한 HTTP 인 / 아웃 인코딩 지원
  • strtoupper와 같은 기능을위한 래퍼를 제공합니다

아이콘

  • 문자셋 변환의 기본
  • 출력 버퍼 핸들러
  • 마임 인코딩 기능
  • 변환
  • 일부 문자열 도우미 (len, substr, strpos, strrpos)
  • 스트림 필터 stream_filter_append($fp, 'convert.iconv.ISO-2022-JP/EUC-JP')

데이터베이스

  • mysql : 테이블과 연결시 문자셋과 콜 레이션 (콜 레이션이 아님). 또한 MySQL을 사용하지 마십시오-msqli 또는 PDO
  • postgresql : pg_set_client_encoding
  • sqlite (3) : 유니 코드 및 국제 지원으로 컴파일되었는지 확인하십시오

다른 몇 가지

  • 세 번째 부분 확장명을 사용하지 않으면 PHP 및 창에서 유니 코드 파일 이름을 사용할 수 없습니다.
  • exec, proc_open 및 기타 명령 줄 호출을 사용하는 경우 ASCII로 모든 것을 보내십시오.
  • 일반 텍스트는 일반 텍스트가 아니며 파일에는 인코딩이 있습니다.
  • iconv 필터를 사용하여 파일을 즉석에서 변환 할 수 있습니다

기능 변경 등이 추가되는 경우이 답변을 업데이트하겠습니다.


답변

이 놀라운 답변에 추가 할 수있는 유일한 것은 utf8 인코딩으로 파일을 저장하는 것을 강조하는 것입니다. 브라우저는 utf8을 코드 인코딩으로 설정하는 것보다 브라우저 가이 속성을 허용한다는 것을 알았습니다. 예를 들어 Notepad ++에는 파일 인코딩을위한 메뉴 옵션이 있으며 현재 인코딩을 보여주고 변경할 수 있습니다. 모든 PHP 파일에는 BOM없이 utf8을 사용합니다.

언젠가 누군가 누군가가 디자인 한 php / mysql 응용 프로그램에 대한 utf8 지원을 추가하도록 요청했습니다. 모든 파일이 ANSI로 인코딩 된 것을 알았으므로 ICONV를 사용하여 모든 파일을 변환하고 데이터베이스 테이블을 사용하도록 변경해야했습니다. utf8 문자셋과 utf8_general_ci 조합, 연결 후 데이터베이스 추상화 계층에 ‘SET NAMES utf8’을 추가하고 (5.3.6 이하를 사용하는 경우 연결 문자열에 charset = utf8을 사용해야 함) php 멀티 바이트를 사용하도록 문자열 함수를 변경하십시오. 문자열 함수에 해당합니다.