如何用 flourish 支持表情符号?
How to support emojis with flourish?
我正在为一个网站使用 flourishlib。我的客户要求我们应该能够在手机上使用表情符号。理论上我们应该将 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%。这将导致更差的性能和更多的存储 space 用完。因此,我们决定仅针对特定 tables.
的特定列切换到 utf8mb4 编码
为了确保一切正常,我检查了几件事。其中,我查看了 flourishlib,发现了几个可疑的部分:
有个fUTF8class,好像不支持utf8mb4
我在 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");
}
在 fSQLSchemaTranslation 我可以看到这个:
$sql = preg_replace('#\)\s*;?\s*$#D', ')ENGINE=InnoDB, CHARACTER SET utf8', $sql);
我怀疑 flourishlib 不支持我们使一些 table 的几列具有 utf8mb4 字符编码的任务。我想知道我们是否可以通过某种方式升级一些东西来提供这种支持。作为最坏的情况,我们可以将 utf8 的每个文本出现都覆盖为 utf8mb4。然而,这将是一个非常丑陋的 hack,我们想知道是否有更好的解决方案。我们应该做这个 hack 还是有更正统的方法?
increase the database's size with 33%.
不正确。每个英文字母仍占用 1 个字节。使用 utf8mb4 的好处是能够存储表情符号和一些汉字。
您不需要 ALTER ... CHANGE
列。除了你可能有一个罐头 VARCHAR(255)
有问题。不要简单地切换到 191,切换到每列的 'reasonable' 数字。或者什么也不做。 191 仅来自 INDEX
限制。您没有为 每个 列编制索引,是吗?
fUTF8 class, which does not seem to support
向flourishlib投诉。或者放弃它。 (这些论坛中有太多问题是对第 3 方软件包不足的抱怨,而不是 MySQL 本身。)
您 可能 可以在 MySQL 中更改为 utf8mb4,并让 flourishlib 忽略该更改。从技术上讲,MySQL 的 utf8mb4 符合世界其他地方的 utf8 概念; MySQL 的 utf8 是一个不完整的实现。
$this->execute("SET NAMES 'utf8'");
如果您能看到这段代码,您可以更改它。
我已经解决了这个问题。我通过更改列字符集和排序规则更改了我想支持表情符号的表,如下所示:
ALTER TABLE table_name CHANGE column_name column_name text CHARACTER SET utf8mb4 COLLATE utf8mb4_unicode_ci;
在那之后,我不得不进行一些丑陋的修改以使 flourishlib 能够支持表情符号。
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
对象。
我正在为一个网站使用 flourishlib。我的客户要求我们应该能够在手机上使用表情符号。理论上我们应该将 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%。这将导致更差的性能和更多的存储 space 用完。因此,我们决定仅针对特定 tables.
的特定列切换到 utf8mb4 编码为了确保一切正常,我检查了几件事。其中,我查看了 flourishlib,发现了几个可疑的部分:
有个fUTF8class,好像不支持utf8mb4
我在 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"); }
在 fSQLSchemaTranslation 我可以看到这个:
$sql = preg_replace('#\)\s*;?\s*$#D', ')ENGINE=InnoDB, CHARACTER SET utf8', $sql);
我怀疑 flourishlib 不支持我们使一些 table 的几列具有 utf8mb4 字符编码的任务。我想知道我们是否可以通过某种方式升级一些东西来提供这种支持。作为最坏的情况,我们可以将 utf8 的每个文本出现都覆盖为 utf8mb4。然而,这将是一个非常丑陋的 hack,我们想知道是否有更好的解决方案。我们应该做这个 hack 还是有更正统的方法?
increase the database's size with 33%.
不正确。每个英文字母仍占用 1 个字节。使用 utf8mb4 的好处是能够存储表情符号和一些汉字。
您不需要 ALTER ... CHANGE
列。除了你可能有一个罐头 VARCHAR(255)
有问题。不要简单地切换到 191,切换到每列的 'reasonable' 数字。或者什么也不做。 191 仅来自 INDEX
限制。您没有为 每个 列编制索引,是吗?
fUTF8 class, which does not seem to support
向flourishlib投诉。或者放弃它。 (这些论坛中有太多问题是对第 3 方软件包不足的抱怨,而不是 MySQL 本身。)
您 可能 可以在 MySQL 中更改为 utf8mb4,并让 flourishlib 忽略该更改。从技术上讲,MySQL 的 utf8mb4 符合世界其他地方的 utf8 概念; MySQL 的 utf8 是一个不完整的实现。
$this->execute("SET NAMES 'utf8'");
如果您能看到这段代码,您可以更改它。
我已经解决了这个问题。我通过更改列字符集和排序规则更改了我想支持表情符号的表,如下所示:
ALTER TABLE table_name CHANGE column_name column_name text CHARACTER SET utf8mb4 COLLATE utf8mb4_unicode_ci;
在那之后,我不得不进行一些丑陋的修改以使 flourishlib 能够支持表情符号。
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
对象。