etc./StackOverFlow

모든 방법을 통해 UTF-8

청렴결백한 만능 재주꾼 2023. 4. 20. 02:24
반응형

질문자 :mercutio


새 서버를 설정 중이고 웹 응용 프로그램에서 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에서:

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

       $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 메타데이터를 통해 ).

  • default_charset php.ini 옵션을 사용하거나 수동으로 Content-Type MIME 헤더를 직접 발행할 수 있습니다. 이는 더 많은 작업이지만 동일한 효과를 가집니다.

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

입력 :

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

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

    • HTML5 이전의 HTML만 해당 : 브라우저에서 보낸 모든 데이터가 UTF-8로 되어 있기를 원합니다. 불행히도 이것을 안정적으로 수행하는 유일한 방법은 <form> 태그에 accept-charset 속성을 <form ... accept-charset="UTF-8"> .
    • HTML5 이전의 HTML만 해당 : W3C HTML 사양에서는 클라이언트가 기본적으로 서버가 제공한 모든 문자 집합에서 양식을 서버로 다시 보내도록 "해야" 한다고 명시되어 있습니다. 그러나 이는 분명히 권장 사항일 뿐이므로 모든 단일 <form> 태그.

기타 코드 고려 사항 :

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

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

  • PHP의 내장 문자열 연산은 기본적으로 UTF-8 안전 하지 않습니다. 일반 PHP 문자열 연산(예: 연결)으로 안전하게 수행할 수 있는 몇 가지 작업이 있지만 대부분의 경우 동등한 mbstring 함수를 사용해야 합니다.

  • 당신이 무엇을 하고 있는지 알기 위해서는(읽기: 엉망이 되지 않도록), 당신은 정말로 UTF-8과 그것이 가능한 가장 낮은 수준에서 어떻게 작동하는지 알아야 합니다. 알아야 할 모든 것을 배울 수 있는 좋은 리소스를 보려면 utf8.com 의 링크를 확인하십시오.


chazomaticus

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 선언)를 모두 사용하는 것이 좋습니다.


mercator

default_charset 을 설정하는 것 외에도 출력 전에 코드 내에서 header() 를 사용하여 올바른 문자 집합을 보낼 수 있습니다.

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

PHP에서 유니코드로 작업하는 것은 대부분의 문자열 함수가 유니코드에서 작동하지 않으며 일부는 문자열을 완전히 조작 할 수 있다는 것을 깨닫는 한 쉽습니다. PHP는 "문자"를 1바이트 길이로 간주합니다. 때때로 이것은 괜찮습니다(예를 들어, explode() 는 바이트 시퀀스만 찾고 이를 구분 기호로 사용하므로 실제로 찾는 문자가 무엇인지는 중요하지 않습니다. 그러나 함수가 실제로 문자에 대해 작동하도록 설계된 다른 경우에는 PHP가 텍스트에 유니코드로 발견되는 멀티바이트 문자가 있다는 것을 인식하지 못합니다.

확인하기에 좋은 라이브러리는 phputf8 입니다. 이것은 UTF8 문자열에서 안전하게 작업할 수 있도록 모든 "나쁜" 기능을 다시 작성합니다. 이를 위해 mbstring 확장과 같은 확장도 있지만 이식성이 더 높기 때문에 라이브러리를 사용하는 것을 선호합니다(그러나 저는 대중 시장 제품을 작성하므로 이것이 중요합니다). 그러나 phputf8은 어쨌든 성능을 향상시키기 위해 mbstring을 뒤에서 사용할 수 있습니다.


chroder

경고: 이 답변은 PHP 5.3.5 이하에 적용됩니다. PHP 버전 5.3.6(2011년 3월 출시) 이상에서는 사용하지 마십시오.

PDO + MySQL 및 깨진 UTF-8 인코딩에 대한 Palec의 답변 과 비교하십시오.


나는 PDO를 사용하는 누군가와 관련된 문제를 발견했고 대답은 PDO 연결 문자열에 이것을 사용하는 것이 었습니다.

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

내가 가져온 사이트는 다운됐지만 다행히 구글 캐시를 이용해 구할 수 있었다.


Jim

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

참고로 mb_internal_encoding() 을 실행하여 내부 인코딩이 utf-8이 아니라는 것을 mb_internal_encoding("UTF-8"); .


JDelage

우선, < 5.3PHP에 있다면 아니요. 해결해야 할 문제가 너무 많습니다.

유니코드 , 문자소 , 문자열 연산 , 현지화 등을 잘 지원 하는 intl 라이브러리에 대해 언급한 사람이 아무도 없다는 사실에 놀랐습니다. 아래를 참조하세요.

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

국제

좋은:

  • ICU 라이브러리 주변 래퍼
  • 표준화된 로케일, 스크립트당 로케일 설정
  • 숫자 서식
  • 통화 형식
  • 메시지 형식(gettext 대체)
  • 달력, 날짜, 시간대 및 시간
  • 음역자
  • 스푸핑 검사기
  • 리소스 번들
  • 변환기
  • IDN 지원
  • 자소
  • 대조
  • 반복자

나쁜:

  • zend_multibyte를 지원하지 않습니다.
  • HTTP 입력 출력 변환을 지원하지 않습니다
  • 함수 오버로딩을 지원하지 않습니다

mb_string

  • zend_multibyte 지원 활성화
  • 투명한 HTTP 입출력 인코딩 지원
  • strtoupper와 같은 기능에 대한 일부 래퍼 제공

아이콘

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

데이터베이스

  • MySQL: 테이블 및 연결(데이터 정렬이 아님)에 대한 문자 집합 및 데이터 정렬. 또한 mysql - mysqli 또는 PDO를 사용하지 마십시오.
  • postgresql: pg_set_client_encoding
  • sqlite(3): 유니코드 및 intl 지원으로 컴파일되었는지 확인하십시오.

다른 잡다한 것들

  • 제3의 확장자를 사용하지 않는 한 PHP 및 Windows에서 유니코드 파일 이름을 사용할 수 없습니다.
  • exec, proc_open 및 기타 명령줄 호출을 사용하는 경우 모든 것을 ASCII로 보냅니다.
  • 일반 텍스트는 일반 텍스트가 아니며 파일에는 인코딩이 있습니다.
  • iconv 필터를 사용하여 즉석에서 파일을 변환할 수 있습니다.

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


Jimmy Kane

이 놀라운 답변에 추가할 유일한 것은 utf8 인코딩으로 파일을 저장하는 것을 강조하는 것입니다. 브라우저가 utf8을 코드 인코딩으로 설정하는 것보다 이 속성을 수락한다는 것을 알았습니다. 예를 들어 메모장 ++에는 파일 인코딩을 위한 메뉴 옵션이 있고 현재 인코딩을 보여주고 변경할 수 있도록 해주는 것과 같이 괜찮은 텍스트 편집기가 이를 보여줍니다. 내 모든 PHP 파일에 대해 BOM 없이 utf8을 사용합니다.

얼마 전에 누군가 다른 사람이 설계한 php/mysql 응용 프로그램에 대한 utf8 지원을 추가해 달라고 요청했습니다. 모든 파일이 ANSI로 인코딩되어 있으므로 ICONV를 사용하여 모든 파일을 변환하고 사용하도록 데이터베이스 테이블을 변경해야 했습니다. utf8 charset 및 utf8_general_ci 조합, 연결 후 데이터베이스 추상화 계층에 'SET NAMES utf8' 추가(5.3.6 또는 이전 버전을 사용하는 경우 연결 문자열에서 charset=utf8을 사용해야 함) php 멀티바이트를 사용하도록 문자열 함수를 변경합니다. 문자열 함수에 해당합니다.


Puerto AGP

최근에 strtolower() 를 사용하면 특수 문자 다음에 데이터가 잘리는 문제가 발생할 수 있음을 발견했습니다.

해결책은 사용하는 것이 었습니다.

 mb_strtolower($string, 'UTF-8');

mb_는 멀티바이트를 사용합니다. 더 많은 문자를 지원하지만 일반적으로 약간 느립니다.


Miguel Stevens

PHP에서는 멀티바이트 함수 를 사용하거나 mbstring.func_overload를 켜야 합니다. 그렇게 하면 1바이트 이상을 차지하는 문자가 있는 경우 strlen과 같은 것이 작동합니다.

또한 응답의 문자 집합을 식별해야 합니다. 위와 같이 AddDefaultCharset을 사용하거나 헤더를 반환하는 PHP 코드를 작성할 수 있습니다. (또는 HTML 문서에 META 태그를 추가할 수 있습니다.)


JW.

나는 방금 같은 문제를 겪었고 PHP 매뉴얼에서 좋은 해결책을 찾았습니다.

모든 파일 인코딩을 UTF8로 변경한 다음 연결의 기본 인코딩을 변경했습니다. 이것은 모든 문제를 해결했습니다.

 if (!$mysqli->set_charset("utf8")) { printf("Error loading character set utf8: %s\n", $mysqli->error); } else { printf("Current character set: %s\n", $mysqli->character_set_name()); }

소스보기


Abdul Sadik Yalcin

PHP의 유니코드 지원은 여전히 큰 혼란입니다. ISO8859 문자열(내부적으로 사용)을 utf8로 변환할 수 있지만 기본적으로 유니코드 문자열로 작업하는 기능이 부족합니다. 따라서 적절한 utf8 지원을 위해 별도의 라이브러리를 사용하거나 모든 문자열 처리 기능을 직접 다시 작성해야 합니다.

쉬운 부분은 HTTP 헤더와 데이터베이스 등에서 charset을 지정하는 것입니다. 그러나 PHP 코드가 유효한 UTF8을 출력하지 않는 경우에는 아무 것도 중요하지 않습니다. 그것은 어려운 부분이며 PHP는 거의 도움이 되지 않습니다. (나는 PHP6이 이것의 최악의 문제를 해결해야 한다고 생각하지만, 아직 한참 멀었다)


jalf

MySQL 서버가 클라이언트로 PHP가 아닌 문자 집합을 결정하도록 하려면(이전 동작, 내 의견으로는 선호) skip-character-set-client-handshakemy.cnf [mysqld] 아래에 추가해 보십시오. mysql 다시 시작하십시오.

UTF8 이외의 다른 것을 사용하는 경우 문제가 발생할 수 있습니다.


Budimir Grom

최고 답변은 훌륭합니다. 다음은 일반 debian/php/mysql 설정에서 수행한 작업입니다.

 // storage // debian. apparently already utf-8 // retrieval // the mysql database was stored in utf-8, // but apparently php was requesting iso. this worked: // ***notice "utf8", without dash, this is a mysql encoding*** mysql_set_charset('utf8'); // delivery // php.ini did not have a default charset, // (it was commented out, shared host) and // no http encoding was specified in the apache headers. // this made apache send out a utf-8 header // (and perhaps made php actually send out utf-8) // ***notice "utf-8", with dash, this is a php encoding*** ini_set('default_charset','utf-8'); // submission // this worked in all major browsers once apache // was sending out the utf-8 header. i didnt add // the accept-charset attribute. // processing // changed a few commands in php, like substr, // to mb_substr

그게 전부였다 !


commonpike

mysql 솔루션을 원하는 경우 서버 마이그레이션 후 내 프로젝트 중 2개에서 비슷한 문제가 발생했습니다. 많은 솔루션을 검색하고 시도한 후에 이 솔루션이 작동하기 전에 /아무것도 발견하지 못했습니다):

 mysqli_set_charset($con,"utf8");

내 구성 파일에 이 줄을 추가하면 모든 것이 잘 작동합니다!

html 쿼리에서 삽입을 해결하려고 할 때 https://www.w3schools.com/PHP/func_mysqli_set_charset.asp 이 솔루션을 찾았습니다.

행운을 빕니다!


castro_pereira

참고 사항:

????????? 로 표시되는 문제에 직면하고 있습니다. , 당신은 질문을 했고 이 표준 질문에 대한 참조로 닫혔습니다. 당신은 모든 것을 시도했지만 당신이 무엇을 하든 여전히 ?????????? MySQL .

그것은 주로 잘못된 문자 집합을 사용하여 데이터베이스에 삽입되어 실제로 물음표 문자로 변환 및 저장된 이전 데이터 를 테스트하고 있기 때문입니다 ? . 즉, 원본 텍스트를 영원히 잃어버리고 무엇을 시도하든 ??????? .

이 질문의 답변에서 배운 것을 새로운 데이터에 다시 적용하면 문제를 해결할 수 있습니다.


Accountant م

connection.php에서: mysqli_set_charset($con,"utf8"); 그리고 SQL 데이터 정렬에서 utf=8


Ijaz Ahmed Bhatti

출처 : http:www.stackoverflow.com/questions/279170/utf-8-all-the-way-through

반응형