我正在设置一个新的服务器,并希望在我的web应用程序中完全支持UTF-8。我过去曾在现有的服务器上尝试过这种方法,但似乎总是不得不回到ISO-8859-1。
我到底需要在哪里设置编码/字符集?我知道我需要配置Apache、MySQL和PHP来做到这一点-是否有一些标准的检查表,我可以遵循,或者排除哪里发生了不匹配?
这是一个新的Linux服务器,运行MySQL 5, PHP, 5和Apache 2。
我正在设置一个新的服务器,并希望在我的web应用程序中完全支持UTF-8。我过去曾在现有的服务器上尝试过这种方法,但似乎总是不得不回到ISO-8859-1。
我到底需要在哪里设置编码/字符集?我知道我需要配置Apache、MySQL和PHP来做到这一点-是否有一些标准的检查表,我可以遵循,或者排除哪里发生了不匹配?
这是一个新的Linux服务器,运行MySQL 5, PHP, 5和Apache 2。
当前回答
首先,如果你使用的是5.3之前的PHP,那就不需要了。你有一大堆问题要解决。
我很惊讶没有人提到intl库,这个库很好地支持Unicode、字母、字符串操作、本地化等等,见下文。
我将引用Elizabeth Smith在PHPBenelux'14上的幻灯片中关于PHP中Unicode支持的一些信息
INTL
好:
ICU库的包装 标准化区域设置,每个脚本设置区域 数字格式 货币格式 消息格式化(替换gettext) 日历,日期,时区和时间 Transliterator Spoofchecker 资源包 转换器 印度尼西亚的支持 字母 排序 迭代器
Bad:
不支持zend_multibyte 不支持HTTP输入输出转换 不支持函数重载
mb_string
启用zend_多字节支持 支持透明的HTTP in/out编码 为strtoupper等功能提供一些包装器
ICONV
主要用于字符集转换 输出缓冲区处理程序 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):确保它是在Unicode和intl支持下编译的
其他一些陷阱
除非使用第三部分扩展,否则不能在PHP和windows中使用Unicode文件名。 如果使用exec、proc_open和其他命令行调用,则以ASCII格式发送所有内容 纯文本不是纯文本,文件有编码 你可以用iconv过滤器转换文件
其他回答
警告:此答案适用于PHP 5.3.5及以下版本。不要在PHP 5.3.6版本(2011年3月发布)或更高版本中使用它。 比较Palec的回答PDO + MySQL和破碎的UTF-8编码。
我发现了一个问题,有人使用PDO,答案是使用这个PDO连接字符串:
$pdo = new PDO(
'mysql:host=mysql.example.com;dbname=example_db',
"username",
"password",
array(PDO::MYSQL_ATTR_INIT_COMMAND => "SET NAMES utf8"));
上面的答案很好。以下是我在常规Debian、PHP和MySQL设置中所做的:
// Storage
// Debian. Apparently already UTF-8
// Retrieval
// The MySQL database was stored in UTF-8,
// but apparently PHP was requesting ISO 8859-1. This worked:
// ***notice "utf8", without dash, this is a MySQL encoding***
mysql_set_charset('utf8');
// Delivery
// File *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 didn’t add
// the accept-charset attribute.
// Processing
// Changed a few commands in PHP, like substr(),
// to mb_substr()
就这些!
如果你想让MySQL服务器来决定字符集,而不是PHP作为客户端(旧行为;最好,在我看来),尝试添加skip-character-set-client-handshake到my.cnf,在[mysqld]下,并重新启动mysql。
如果您使用的不是UTF-8,这可能会带来麻烦。
我最近发现,使用strtolower()可能会导致数据在特殊字符之后被截断的问题。
解决办法就是使用
mb_strtolower($string, 'UTF-8');
mb_使用MultiByte。它支持更多的字符,但总体来说有点慢。
除了在php.ini中设置default_charset外,你还可以在输出之前使用header()在你的代码中发送正确的字符集:
header('Content-Type: text/html; charset=utf-8');
在PHP中使用Unicode是很容易的,只要您认识到大多数字符串函数都不能使用Unicode,而且有些函数可能会完全破坏字符串。PHP认为“字符”长度为1字节。有时这是可以的(例如,explosion()只查找字节序列并将其用作分隔符——因此查找的实际字符并不重要)。但在其他时候,当函数实际设计为处理字符时,PHP并不知道您的文本中有Unicode中可以找到的多字节字符。
phputf8是一个很好的库。这将重写所有“坏”函数,因此您可以安全地处理UTF8字符串。也有像mb_string扩展这样的扩展试图为您做这件事,但我更喜欢使用库,因为它更可移植(但我写的是大众市场产品,所以这对我来说很重要)。但是phputf8可以在幕后使用mb_string来提高性能。