8wDlpd.png
8wDFp9.png
8wDEOx.png
8wDMfH.png
8wDKte.png

始终使用 UTF-8

Faisal Feroz 1月前

87 0

我正在设置一个新服务器,并希望在我的 Web 应用程序中完全支持 UTF-8。我过去曾在现有服务器上尝试过此操作,但似乎总是最终不得不回退到 ISO-8859-1。这...

我正在设置一个新服务器,并希望在我的 Web 应用程序中完全支持 UTF-8。我过去曾在现有服务器上尝试过此操作,但似乎总是最终不得不回退到 ISO-8859-1。

我到底需要在哪里设置编码/字符集?我知道我需要配置 Apache、MySQL 和 PHP 才能做到这一点 — 是否有一些我可以遵循的标准清单,或者可以排除不匹配发生的位置故障?

这是用于新的 Linux 服务器,运行 MySQL 5、PHP 5 和 Apache 2。

帖子版权声明 1、本帖标题:始终使用 UTF-8
    本站网址:http://xjnalaquan.com/
2、本网站的资源部分来源于网络,如有侵权,请联系站长进行删除处理。
3、会员发帖仅代表会员个人观点,并不代表本站赞同其观点和对其真实性负责。
4、本站一律禁止以任何方式发布或转载任何违法的相关信息,访客发现请向站长举报
5、站长邮箱:yeweds@126.com 除非注明,本帖由Faisal Feroz在本站《sql-server》版块原创发布, 转载请注明出处!
最新回复 (0)
  • 最佳答案非常好。以下是我在常规 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 以外的其他编码,这可能会造成麻烦。

  • PHP 对 Unicode 的支持仍然很混乱。虽然它能够将 ISO 8859 字符串(它在内部使用)转换为 UTF-8,但它缺乏原生处理 Unicode 字符串的能力,这意味着所有字符串处理函数都会破坏和损坏您的字符串。

    因此,您必须使用单独的库来获得正确的 UTF-8 支持,或者自己重写所有字符串处理函数。

    最简单的部分就是在 HTTP 标头和数据库等中指定字符集,但如果您的 PHP 代码不能输出有效的 UTF-8,那么这些都毫无意义。这才是最难的部分,而 PHP 在这方面几乎不会给您任何帮助。(我认为 PHP 6 应该可以解决这一问题,但这还需要一段时间。)

  • @FunkFortyNiner 注意:set_charset(\'utf8\') 可能有效,但行为会有所不同(请参阅有关 utf8 和 utf8mb4 之间的差异以及 mysql 版本历史的注释)。如果必须使用 utf8,并且仅当您知道自己在做什么时才使用!

  • 我花了一个小时试图找出我正在处理的页面上的编码问题,我通常很擅长解决问题。我总是参考这个页面,你的回答对我帮助很大。我投了赞成票。在我的例子中,set_charset('utf8mb4') 不起作用,但 >set_charset(\'utf8\') 起作用,而其他答案中实际上没有显示这一点。

  • 我刚刚遇到了同样的问题,并在 PHP 手册中找到了一个很好的解决方案。

    我将所有文件的编码都改为 UTF8,然后将连接的默认编码也改为 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());
    }
    

    查看源代码

  • 需要注意的是,由于上述 @JW 评论中提到的问题,mbstring.func_overload 功能从 PHP 7.2 开始被弃用。因此,最好的建议是:是的,您绝对应该使用 mbstring 函数,但不要使用过载功能让标准函数以多字节方式工作。

  • 在 PHP 中,您需要使用 多字节函数 ,或者打开 mbstring.func_overload 。这样,如果您有占用多个字节的字符,那么像 strlen 这样的东西就可以工作。

    您还需要确定响应的字符集。您可以像上面一样使用 AddDefaultCharset,也可以编写返回标头的 PHP 代码。(或者,您可以将 META 标记添加到 HTML 文档中。)

  • 我最近发现使用 strtolower() 可能会导致特殊字符后数据被截断的问题。

    解决方案是使用

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

    mb_ 使用 MultiByte。它支持更多字符,但总体来说速度较慢。

  • 我要补充的是,这些令人惊叹的答案强调以 UTF-8 编码保存文件,我注意到浏览器接受此属性,而不是将 UTF-8 设置为代码编码。任何像样的文本编辑器都会向您显示这一点。例如, Notepad++ 有一个文件编码菜单选项,它会显示当前编码并允许您更改它。对于我的所有 PHP 文件,我都使用不带 8 的 UTF- BOM .

    前段时间,有人让我为别人设计的 PHP 和 MySQL 应用程序添加 UTF-8 支持。我注意到所有文件都是用 ANSI 编码的,所以我不得不使用 iconv 转换所有文件,将数据库表更改为使用 UTF-8 字符集和 utf8_general_ci 排序,在连接后将“SET NAMES utf8”添加到数据库抽象层(如果使用 5.3.6 或更早版本。否则,您必须在连接字符串中使用 charset=utf8)并更改字符串函数以使用等效的 PHP 多字节字符串函数。

  • 是的,没错。Mysqli 和 PDO 可以使用其原生驱动程序。如果您使用 --with-mysqli=mysqlnd --with-pdo-mysql=mysqlnd 选项编译 php,它们也可以使用 mysqlnd 驱动程序。

  • 引用 13

    首先,如果你使用的是 PHP 5.3 之前的版本,那么不行。你有很多问题需要解决。

    我很惊讶没有人提到 intl 库,该库对 Unicode , 字素字符串 , 操作 , 本地化 等有很好的支持,见下文。

    Elizabeth Smith PHPBenelux'14 slides 幻灯片 中关于 PHP 中 Unicode 支持的一些信息

    国际

    好的:

    • ICU 库的包装器
    • 标准化语言环境,按脚本设置语言环境
    • 数字格式
    • 货币格式
    • 消息格式化(替代 gettext)
    • 日历、日期、时区和时间
    • 音译器
    • 欺骗检测工具
    • 资源包
    • 转换器
    • IDN 支持
    • 字素
    • 排序规则
    • 迭代器

    坏的:

    • 不支持 zend_multibyte
    • 不支持HTTP输入输出转换
    • 不支持函数重载

    mb_字符串

    • 启用 zend_multibyte 支持
    • 支持透明 HTTP 输入/输出编码
    • 提供一些功能的包装器,例如 strtoupper

    图标

    • 主要用于字符集转换
    • 输出缓冲区处理程序
    • 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 和国际支持进行编译的

    其他一些问题

    • 除非使用第三方扩展,否则您不能在 PHP 和 Windows 中使用 Unicode 文件名。
    • 如果您使用 exec、proc_open 和其他命令行调用,请以 ASCII 格式发送所有内容
    • 纯文本不是纯文本,文件有编码
    • 您可以使用 iconv 过滤器即时转换文件
  • 在我的例子中,我使用的是 mb_split ,它使用正则表达式。因此,我还必须手动确保正则表达式编码为 UTF-8,方法是: mb_regex_encoding('UTF-8');

    附注:我还通过运行发现 mb_internal_encoding() 内部编码不是 UTF-8,我通过运行更改了它 mb_internal_encoding("UTF-8"); .

  • 另请参阅 Palec 对 PDO + MySQL 和损坏的 UTF-8 编码的回答。

  • 引用 16

    进一步研究后发现,只有 5.3.6 之前的 PHP 版本才需要这样做。另请参阅:http://.com/a/4361485/2286722(尽管它们使用单​​独的 $dbh->exec(\'set names utf8\');;但我更喜欢这里介绍的方法)。顺便说一句,PHP 手册中也有类似的注释:php.net/manual/en/pdo.construct.php#96325。

  • 警告: 此答案适用于 PHP 5.3.5 及更低版本。请勿将其用于 PHP 版本 5.3.6(2011 年 3 月发布)或更高版本。

    Palec's answer to PDO + MySQL and broken UTF-8 encoding .


    时遇到一个问题 PDO ,答案是将其用于 PDO 连接字符串:

    $pdo = new PDO(
        'mysql:host=mysql.example.com;dbname=example_db',
        "username",
        "password",
        array(PDO::MYSQL_ATTR_INIT_COMMAND => "SET NAMES utf8"));
    
  • 除了在 php.ini 中设置之外 default_charset 在任何输出之前使用代码 header() 发送正确的字符集

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

    只要您意识到大多数 字符串函数不适用于 Unicode,并且有些函数可能会完全破坏字符串 ,那么在 PHP 中使用 Unicode 就很容易了。PHP 认为 \'字符\' 的长度为 1 个字节。有时这是可以的(例如, explode() 仅查找字节序列并将其用作分隔符 - 因此您查找的实际字符并不重要)。但其他时候,当该函数实际上设计用于处理 characters ,PHP 不知道您的文本具有使用 Unicode 找到的多字节字符。

    一个值得一试的好库是 phputf8 。它重写了所有“坏”函数,因此您可以安全地处理 UTF8 字符串。还有一些扩展,例如 mb_string 扩展,也可以为您完成此操作,但我更喜欢使用该库,因为它更易于移植(但我编写的是大众市场产品,因此这对我来说很重要)。但无论如何,phpputf8 可以在后台使用 mb_string 来提高性能。

  • 我想对 chazomaticus 的出色回答 :

    也不要忘记 META 标签(像这样,或者 它的 HTML4 或 XHTML 版本 ):

    <meta charset="utf-8">
    

    这看起来微不足道,但 IE7 之前曾给我带来过这个问题。

    我做的一切都是正确的;数据库、数据库连接和 Content-Type HTTP 标头都设置为 UTF-8,并且它在所有其他浏览器中都运行良好,但 Internet Explorer 仍然坚持使用“西欧”编码。

    原来是页面缺少 META 标签。添加该标签后问题就解决了。

    W3C 实际上有一个相当大的 部分专门用于 I18N 。他们有许多与此问题相关的文章 - 描述了 HTTP,(X)HTML 和 CSS 方面的问题:

    • 常见问题解答:将 (X)HTML 页面编码更改为 UTF-8
    • 在 HTML 中声明字符编码
    • 教程:XHTML、HTML 和 CSS 中的字符集和编码
    • 设置 HTTP 字符集参数

    他们建议同时使用 HTTP 标头和 HTML 元标记(或者在 XHTML 作为 XML 的情况下使用 XML 声明)。

  • @chazomaticus 我的数据库已经存储了问号而不是希伯来语文本,那么我如何从问号中获取原始文本?

返回
作者最近主题: