0

我正在为网站使用繁荣库。我的客户要求我们应该能够在手机上使用表情符号。理论上,我们应该将 MySQL 数据库的字符编码从 utf8 更改为 utf8mb4。

到目前为止,一切都很好,但是,如果我们进行此切换,如下所示:

# For each database:
ALTER DATABASE database_name CHARACTER SET = utf8mb4 COLLATE utf8mb4_unicode_ci;
# For each table:
ALTER TABLE table_name CONVERT TO CHARACTER SET utf8mb4 COLLATE utf8mb4_unicode_ci;
# For each column:
ALTER TABLE table_name CHANGE column_name column_name VARCHAR(191) CHARACTER SET utf8mb4 COLLATE utf8mb4_unicode_ci;
# (Don’t blindly copy-paste this! The exact statement depends on the column type, maximum length, and other properties. The above line is just an example for a `VARCHAR` column.)

然后每个字符将使用四个字节而不是三个字节。这将使数据库的大小增加 33%。这将导致更差的性能和更多的存储空间被用完。因此,我们决定只为特定表的特定列切换到 utf8mb4 编码。

为了确保一切正常,我检查了几件事。其中,我检查了flavourlib,发现了几个可疑的部分:

  1. 有一个fUTF8类,好像不支持utf8mb4

  2. 在 fDatabase 我引用了一些发现:

    if ($this->connection && function_exists('mysql_set_charset') && !mysql_set_charset('utf8', $this->connection)) {
        throw new fConnectivityException(
            'There was an error setting the database connection to use UTF-8'
        );
    }
    //...
    // Make MySQL act more strict and use UTF-8
    if ($this->type == 'mysql') {
        $this->execute("SET SQL_MODE = 'REAL_AS_FLOAT,PIPES_AS_CONCAT,ANSI_QUOTES,IGNORE_SPACE'");
        $this->execute("SET NAMES 'utf8'");
        $this->execute("SET CHARACTER SET utf8");
    }
    
  3. 在 fSQLSchemaTranslation 我可以看到:

    $sql = preg_replace('#\)\s*;?\s*$#D', ')ENGINE=InnoDB, CHARACTER SET utf8', $sql);
    

我怀疑繁荣库不支持我们使几个表的几列具有utf8mb4字符编码的任务。我想知道我们是否可以以某种方式升级某些东西来提供这种支持。作为最坏的情况,我们可以将每个文本出现的 utf8 覆盖为 utf8mb4。但是,这将是一个非常丑陋的 hack,我们想知道是否有更好的解决方案。我们应该进行这种破解还是有更正统的方法?

4

2 回答 2

1

我已经解决了这个问题。我通过更改列字符集和排序规则更改了我想要支持表情符号的表,如下所示:

ALTER TABLE table_name CHANGE column_name column_name text CHARACTER SET utf8mb4 COLLATE utf8mb4_unicode_ci;

在那之后,我不得不做一些丑陋的 hack 以使繁荣库能够支持表情符号。

fDatabase.php

第 685 行:

        if ($this->connection && function_exists('mysql_set_charset') && !mysql_set_charset('utf8mb4', $this->connection)) {
            throw new fConnectivityException(
                'There was an error setting the database connection to use UTF-8'
            );
        }

第 717 行保持不变,如果更改此行,一切都会崩溃:

if ($this->connection && function_exists('mysqli_set_charset') && !mysqli_set_charset($this->connection, 'utf8')) {

第 800 行:

    // Make MySQL act more strict and use UTF-8
    if ($this->type == 'mysql') {
        $this->execute("SET SQL_MODE = 'REAL_AS_FLOAT,PIPES_AS_CONCAT,ANSI_QUOTES,IGNORE_SPACE'");
        $this->execute("SET NAMES 'utf8mb4'");
        $this->execute("SET CHARACTER SET utf8mb4");
    }

fSQLSchemaTranslation.php

第 1554 行:

$sql = preg_replace('#\)\s*;?\s*$#D', ')ENGINE=InnoDB, CHARACTER SET utf8mb4', $sql);

fXML.php

第 403 行:

    if (preg_replace('#[^a-z0-9]#', '', strtolower($encoding)) == 'utf8mb4') {
        // Remove the UTF-8 BOM if present
        $xml = preg_replace("#^\xEF\xBB\xBF#", '', $xml);
        fCore::startErrorCapture(E_NOTICE);
        $cleaned = self::iconv('UTF-8', 'UTF-8', $xml);
        if ($cleaned != $xml) {
            $xml = self::iconv('Windows-1252', 'UTF-8', $xml);
        }
        fCore::stopErrorCapture();
    }

最后,当对任何受影响的列进行修改时,我执行以下操作:

App::db()->query("set names 'utf8mb4'");

这基本上触发了对象的->query()执行。fDatabase

于 2015-09-09T13:14:29.417 回答
-1

将数据库的大小增加 33%。

不对。每个英文字母仍然占用 1 个字节。使用 utf8mb4 获得的是存储表情符号和一些汉字的能力。

你不应该需要ALTER ... CHANGE这些列。除了你可能有一个VARCHAR(255)有问题的罐头。不要简单地切换到 191,而是为每一列切换到一个“合理”的数字。或者什么都不做。191 仅来自一个INDEX限制。你没有索引每一列,是吗?

fUTF8 类,好像不支持

向繁荣库投诉。或者放弃它。(这些论坛中的太多问题是抱怨 3rd 方包不足,而不是 MySQL 本身。)

也许可以在 MySQL 中更改为 utf8mb4 并让繁荣库忽略更改。从技术上讲,MySQL 的 utf8mb4 与世界其他地方的 utf8 概念相匹配;MySQL 的 utf8 是一个不完整的实现。

$this->execute("SET NAMES 'utf8'");

如果您可以看到此代码,则可以更改它。

于 2015-09-08T06:41:48.347 回答