我正在设置一个新服务器,希望在我的web应用程序中完全支持utf-8。我曾经在现有服务器上尝试过这种方法,结果总是不得不退回到iso-8859-1。我到底需要在哪里设置编码/字符集?我知道我需要配置apache、mysql和php来做到这一点——我是否可以遵循一些标准的检查表,或者对出现不匹配的地方进行故障排除?这是一个新的linux服务器,运行mysql 5、php、5和apache2。
brtdzjyr1#
数据存储:指定 utf8mb4 数据库中所有表和文本列上的字符集。这使得mysql在物理上存储和检索utf-8中本机编码的值。注意mysql将隐式地使用 utf8mb4 如果 utf8mb4_* 指定了排序规则(没有任何显式字符集)。在mysql的旧版本(<5.5.3)中,不幸的是,您将被迫使用 utf8 ,它只支持unicode字符的子集。我真希望我是在开玩笑。数据访问:在应用程序代码(例如php)中,无论使用什么db访问方法,都需要将connection charset设置为 utf8mb4 . 这样,当mysql将数据交给您的应用程序时,它就不会从本机utf-8进行转换,反之亦然。有些驱动程序提供了自己的机制来配置连接字符集,它既更新自己的内部状态,又通知mysql要在连接上使用的编码这通常是首选方法。在php中:如果您在php中使用pdo抽象层≥ 5.3.6,您可以指定 charset 在dsn中:
utf8mb4
utf8mb4_*
utf8
charset
$dbh = new PDO('mysql:charset=utf8mb4');
如果你正在使用mysqli,你可以打电话给 set_charset() :
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 如上所述。输出:如果您的应用程序将文本传输到其他系统,则还需要通知他们字符编码。对于web应用程序,必须通知浏览器发送数据的编码(通过http响应头或html元数据)。在php中,可以使用 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格式。不幸的是,如果要可靠地做到这一点,唯一的方法就是添加 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上的任何链接,获取一些好的资源,了解您需要知道的一切。
mysql_set_charset
SET NAMES 'utf8mb4'
default_charset
Content-Type
json_encode()
JSON_UNESCAPED_UNICODE
mb_check_encoding()
accept-charset
<form>
<form ... accept-charset="UTF-8">
mbstring
rsaldnfx2#
除了设置 default_charset 在php.ini中,可以使用 header() 从代码中,在任何输出之前:
header()
header('Content-Type: text/html; charset=utf-8');
在php中使用unicode是很容易的,只要您意识到大多数字符串函数不能使用unicode,而且有些函数可能会完全破坏字符串。php认为“字符”的长度为1字节。有时这是可以的(例如, explode() 只查找一个字节序列并将其用作分隔符——因此查找实际字符并不重要)。但是其他时候,当函数被设计成处理字符时,php不知道文本中有unicode中的多字节字符。phputf8是一个很好的库。这重写了所有的“坏”函数,因此可以安全地处理utf8字符串。有些扩展,比如mbstring扩展,也尝试为您实现这一点,但我更喜欢使用库,因为它更便于移植(但我编写的是大众市场产品,所以这对我很重要)。但是phputf8可以在幕后使用mbstring来提高性能。
explode()
bprjcwpo3#
就我而言,我用的是 mb_split ,它使用regex。因此,我还必须手动确保regex编码是utf-8 mb_regex_encoding('UTF-8'); 顺便说一句,我还发现 mb_internal_encoding() 内部编码不是utf-8,我通过运行 mb_internal_encoding("UTF-8"); .
mb_split
mb_regex_encoding('UTF-8');
mb_internal_encoding()
mb_internal_encoding("UTF-8");
zzoitvuj4#
首先,如果你的血压低于5.3马力,那就不行。你有很多问题要解决。我很惊讶没有人提到intl库,这个库很好地支持unicode、graphemes、字符串操作、本地化等等,见下文。我将在phpbenelux'14上引用elizabeth smith的slides关于php中unicode支持的一些信息
好的:Package icu图书馆标准化语言环境,按脚本设置语言环境数字格式货币格式消息格式(替换gettext)日历、日期、时区和时间音译器欺骗者资源包转换器idn支持字素校勘迭代器坏的:不支持zend\u多比特不支持http输入输出转换不支持函数重载
启用zend\u多字节支持支持透明的http输入/输出编码提供一些功能 Package ,如strtoupper
字符集转换的主要输出缓冲区处理程序mime编码功能转换一些字符串助手(len、substr、strpos、strrpos)流过滤器 stream_filter_append($fp, 'convert.iconv.ISO-2022-JP/EUC-JP') ###数据库mysql:表和连接上的字符集和排序规则(不是排序规则)。也不要使用mysql-msqli或pdopostgresql:pg\u set\u client\u编码sqlite(3):确保它是用unicode和intl支持编译的
stream_filter_append($fp, 'convert.iconv.ISO-2022-JP/EUC-JP')
除非使用第三部分扩展名,否则不能在php和windows中使用unicode文件名。如果您使用exec、proc\u open和其他命令行调用,请以ascii格式发送所有内容纯文本不是纯文本,文件有编码可以使用iconv过滤器动态转换文件我会更新这个答案,以防事情发生变化,增加功能等。
im9ewurl5#
我要补充的唯一一件事就是强调用utf8编码保存文件,我注意到浏览器接受这个属性而不是将utf8设置为代码编码。任何像样的文本编辑器都会显示这一点,例如notepad++有一个用于文件编码的菜单选项,它会显示当前的编码并允许您更改它。对于我所有的php文件,我都使用utf8而不使用bom。前一段时间,有人让我为别人设计的php/mysql应用程序添加utf8支持,我注意到所有文件都是用ansi编码的,所以我不得不用iconv来转换所有文件,把数据库表改成utf8字符集和utf8\u general\u ci collate,将“set names utf8”添加到连接后的数据库抽象层(如果使用5.3.6或更早版本,则必须在连接字符串中使用charset=utf8)并更改字符串fu
j2datikz6#
我发现有人在使用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缓存获得它。
bkhjykvo7#
我想对查佐马提库斯的完美答案补充一点:也不要忘记meta标记(比如这个,或者它的html4或xhtml版本):
<meta charset="utf-8">
这似乎微不足道,但ie7给我以前的问题。我做的每件事都是对的;数据库、数据库连接和内容类型http头都设置为utf-8,在所有其他浏览器中都可以正常工作,但internetexplorer仍然坚持使用“西欧”编码。结果发现页面缺少meta标签。这就解决了问题。编辑:w3c实际上有一个相当大的部分专门讨论i18n。他们有很多与这个问题相关的文章——描述了http、(x)html和css方面的内容:常见问题解答:将(x)html页面编码更改为utf-8在html中声明字符编码教程:字符集和编码在xhtml,html和css设置http字符集参数他们建议同时使用http头和html元标记(或者在xhtml作为xml的情况下使用xml声明)。
7条答案
按热度按时间brtdzjyr1#
数据存储:
指定
utf8mb4
数据库中所有表和文本列上的字符集。这使得mysql在物理上存储和检索utf-8中本机编码的值。注意mysql将隐式地使用utf8mb4
如果utf8mb4_*
指定了排序规则(没有任何显式字符集)。在mysql的旧版本(<5.5.3)中,不幸的是,您将被迫使用
utf8
,它只支持unicode字符的子集。我真希望我是在开玩笑。数据访问:
在应用程序代码(例如php)中,无论使用什么db访问方法,都需要将connection charset设置为
utf8mb4
. 这样,当mysql将数据交给您的应用程序时,它就不会从本机utf-8进行转换,反之亦然。有些驱动程序提供了自己的机制来配置连接字符集,它既更新自己的内部状态,又通知mysql要在连接上使用的编码这通常是首选方法。在php中:
如果您在php中使用pdo抽象层≥ 5.3.6,您可以指定
charset
在dsn中:如果你正在使用mysqli,你可以打电话给
set_charset()
:如果你坚持使用纯mysql,但是碰巧运行php≥ 5.2.3,你可以打电话
mysql_set_charset
.如果驱动程序没有提供自己的机制来设置连接字符集,您可能需要发出一个查询来告诉mysql应用程序希望如何对连接上的数据进行编码:
SET NAMES 'utf8mb4'
.同样的考虑
utf8mb4
/utf8
如上所述。输出:
如果您的应用程序将文本传输到其他系统,则还需要通知他们字符编码。对于web应用程序,必须通知浏览器发送数据的编码(通过http响应头或html元数据)。
在php中,可以使用
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格式。不幸的是,如果要可靠地做到这一点,唯一的方法就是添加
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上的任何链接,获取一些好的资源,了解您需要知道的一切。
rsaldnfx2#
除了设置
default_charset
在php.ini中,可以使用header()
从代码中,在任何输出之前:在php中使用unicode是很容易的,只要您意识到大多数字符串函数不能使用unicode,而且有些函数可能会完全破坏字符串。php认为“字符”的长度为1字节。有时这是可以的(例如,
explode()
只查找一个字节序列并将其用作分隔符——因此查找实际字符并不重要)。但是其他时候,当函数被设计成处理字符时,php不知道文本中有unicode中的多字节字符。phputf8是一个很好的库。这重写了所有的“坏”函数,因此可以安全地处理utf8字符串。有些扩展,比如mbstring扩展,也尝试为您实现这一点,但我更喜欢使用库,因为它更便于移植(但我编写的是大众市场产品,所以这对我很重要)。但是phputf8可以在幕后使用mbstring来提高性能。
bprjcwpo3#
就我而言,我用的是
mb_split
,它使用regex。因此,我还必须手动确保regex编码是utf-8mb_regex_encoding('UTF-8');
顺便说一句,我还发现mb_internal_encoding()
内部编码不是utf-8,我通过运行mb_internal_encoding("UTF-8");
.zzoitvuj4#
首先,如果你的血压低于5.3马力,那就不行。你有很多问题要解决。
我很惊讶没有人提到intl库,这个库很好地支持unicode、graphemes、字符串操作、本地化等等,见下文。
我将在phpbenelux'14上引用elizabeth smith的slides关于php中unicode支持的一些信息
国际
好的:
Package icu图书馆
标准化语言环境,按脚本设置语言环境
数字格式
货币格式
消息格式(替换gettext)
日历、日期、时区和时间
音译器
欺骗者
资源包
转换器
idn支持
字素
校勘
迭代器
坏的:
不支持zend\u多比特
不支持http输入输出转换
不支持函数重载
mb\U字符串
启用zend\u多字节支持
支持透明的http输入/输出编码
提供一些功能 Package ,如strtoupper
iconv公司
字符集转换的主要
输出缓冲区处理程序
mime编码功能
转换
一些字符串助手(len、substr、strpos、strrpos)
流过滤器
stream_filter_append($fp, 'convert.iconv.ISO-2022-JP/EUC-JP')
###数据库mysql:表和连接上的字符集和排序规则(不是排序规则)。也不要使用mysql-msqli或pdo
postgresql:pg\u set\u client\u编码
sqlite(3):确保它是用unicode和intl支持编译的
一些其他的陷阱
除非使用第三部分扩展名,否则不能在php和windows中使用unicode文件名。
如果您使用exec、proc\u open和其他命令行调用,请以ascii格式发送所有内容
纯文本不是纯文本,文件有编码
可以使用iconv过滤器动态转换文件
我会更新这个答案,以防事情发生变化,增加功能等。
im9ewurl5#
我要补充的唯一一件事就是强调用utf8编码保存文件,我注意到浏览器接受这个属性而不是将utf8设置为代码编码。任何像样的文本编辑器都会显示这一点,例如notepad++有一个用于文件编码的菜单选项,它会显示当前的编码并允许您更改它。对于我所有的php文件,我都使用utf8而不使用bom。
前一段时间,有人让我为别人设计的php/mysql应用程序添加utf8支持,我注意到所有文件都是用ansi编码的,所以我不得不用iconv来转换所有文件,把数据库表改成utf8字符集和utf8\u general\u ci collate,将“set names utf8”添加到连接后的数据库抽象层(如果使用5.3.6或更早版本,则必须在连接字符串中使用charset=utf8)并更改字符串fu
j2datikz6#
我发现有人在使用pdo时出现问题,答案是将此用于pdo连接字符串:
我的网站已经关闭了,但幸运的是,我可以使用google缓存获得它。
bkhjykvo7#
我想对查佐马提库斯的完美答案补充一点:
也不要忘记meta标记(比如这个,或者它的html4或xhtml版本):
这似乎微不足道,但ie7给我以前的问题。
我做的每件事都是对的;数据库、数据库连接和内容类型http头都设置为utf-8,在所有其他浏览器中都可以正常工作,但internetexplorer仍然坚持使用“西欧”编码。
结果发现页面缺少meta标签。这就解决了问题。
编辑:
w3c实际上有一个相当大的部分专门讨论i18n。他们有很多与这个问题相关的文章——描述了http、(x)html和css方面的内容:
常见问题解答:将(x)html页面编码更改为utf-8
在html中声明字符编码
教程:字符集和编码在xhtml,html和css
设置http字符集参数
他们建议同时使用http头和html元标记(或者在xhtml作为xml的情况下使用xml声明)。