Bagaimana cara mengatur header HTTP ke UTF-8 menggunakan PHP yang valid di validator W3C?


319

Saya memiliki beberapa halaman PHP yang menggabungkan berbagai hal menjadi halaman HTML dengan kode berikut.

<meta http-equiv="Content-type" content="text/html; charset=utf-8" />

Namun, ketika saya memvalidasi menggunakan validator W3C muncul dengan:

Pengkodean karakter yang ditentukan dalam header HTTP (iso-8859-1) berbeda dari nilai dalam elemen (utf-8).

Saya cukup baru untuk PHP, dan saya bertanya-tanya apakah saya bisa dan harus mengubah header untuk file PHP agar sesuai dengan file HTML.

Jawaban:


897

Gunakan headeruntuk memodifikasi header HTTP:

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

Catatan untuk memanggil fungsi ini sebelum output apa pun telah dikirim ke klien. Kalau tidak, tajuk sudah dikirim juga dan Anda jelas tidak bisa mengubahnya lagi. Anda dapat memeriksanya dengan headers_sent. Lihat halaman manualheader untuk informasi lebih lanjut.


4
Saya hanya akan menambahkan bahwa ketika Anda mengatur header HTTP dengan benar seperti ini, Anda tidak perlu <meta>tag sama sekali lagi.
Jon

3
@ Jon: Saya akan menggunakan keduanya. Setara HTTP METAdigunakan ketika dokumen HTML tidak dimuat melalui HTTP (misalnya dari disk).
Gumbo

6
Ini hanya akan berfungsi jika Anda menjalankan php, untuk melakukannya untuk halaman statis, Anda harus menyimpan file html Anda AS utf-8. Melakukan hal itu akan menambahkan karakter BOM utf-8 yang dikodekan ke awal file. byte 0xEF, 0xBB, 0xBF ditambahkan ke awal file. Sebagian besar server web akan memperhatikan hal ini dan menerapkan tajuk yang sesuai. Bahkan menyimpan file php Anda sebagai utf-8, akan mencapai hal yang sama.
Rahly

1
@ Jeremy Walton: Bahwa BOM UTF-8 ditambahkan tidak terjadi begitu saja. Bahkan, itu tidak diperlukan untuk UTF-8 karena hanya memiliki satu byte order (tetapi dapat digunakan untuk mengidentifikasi UTF-8).
Gumbo

1
@ Gumbo: tentu, saya menyederhanakan di sini dan menargetkan jauh skenario web yang paling umum (pertanyaannya tampaknya berbicara tentang skenario ini). Mempertimbangkan tingkat pertanyaan yang jelas, mengapa melakukan sesuatu ketika Anda bahkan tidak mengerti apa manfaatnya kelak?
Jon


15

Ini adalah masalah dengan server web Anda mengirimkan header HTTP yang tidak cocok dengan yang Anda tentukan. Untuk instruksi tentang cara membuat server mengirim tajuk yang benar, lihat halaman ini .

Jika tidak, Anda juga dapat menggunakan PHP untuk memodifikasi tajuk, tetapi ini harus dilakukan sebelum mengeluarkan teks apa pun menggunakan kode ini:

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

Informasi lebih lanjut tentang cara mengirim header menggunakan PHP dapat ditemukan dalam dokumentasi untuk fungsi header .


12

Anda juga dapat menggunakan cara yang lebih pendek:

<?php header('Content-Type: charset=utf-8'); ?>

Lihat RFC 2616 . Ini valid untuk menentukan hanya set karakter.


Saya suka opsi ini, karena (saya berasumsi) itu akan memungkinkan Anda untuk mengatur bagian lain dari tipe konten secara terpisah (misalnya, Anda memiliki beberapa halaman teks / polos, dan beberapa halaman teks / html, tetapi semuanya adalah UTF8.) Apakah pemahaman saya benar?
Eric Seastrand

1
Saya tidak dapat menemukan bagian dari RFC 2616 yang mengatakan itu sah untuk menentukan seperti itu. Content-Type = "Content-Type" ":" media-typedanmedia-type = type "/" subtype *( ";" parameter )
AI0867

1
Tidak valid hanya menentukan rangkaian karakter. Ini tidak berlaku per RFC 2616 (yang toh usang) atau per RFC 7231 (yang tidak usang) atau per RFC lainnya. Lihat stackoverflow.com/questions/41994062/...
sontonbarker

10

Untuk implementasi yang benar, Anda perlu mengubah serangkaian hal.

Database (segera setelah koneksi):

mysql_query("SET NAMES utf8");

// Meta tag HTML (probably it's already set): 
meta charset="utf-8"
header php (before any output of the HTML):
header('Content-Type: text/html; charset=utf-8')
table-rows-charset (for each row):
utf8_unicode_ci

4
Koalisi database tidak mempengaruhi output yang dihasilkan oleh PHP karena data dikodekan ke format asli yang dikonfigurasikan untuk digunakan dengan PHP sebelum dikembalikan ke pengguna. OP kedua tidak menyebutkan dia menggunakan MySQL. Ketiga MyISAM sudah usang dan tidak boleh direkomendasikan kecuali Anda tahu apa yang Anda lakukan. Ada alasan InnoDB menjadi default baru.
EWit

akhirnya daftar lengkap semua tempat untuk mengatur pengkodean karakter.
Filip OvertoneSinger Rydlo

mysql_query ("SET NAMES utf8"); sebelum kueri pemilihan saya memperbaiki masalah untuk saya. terima kasih :)
Deepak Goswami

7

PHP mengirimkan tajuk secara otomatis jika diatur untuk menggunakan penyandian internal:

ini_set('default_charset', 'utf-8');
Dengan menggunakan situs kami, Anda mengakui telah membaca dan memahami Kebijakan Cookie dan Kebijakan Privasi kami.
Licensed under cc by-sa 3.0 with attribution required.