12

我有一个大的 php 对象,我想将其序列化并存储在 MySql 数据库中。表编码是UTF-8,保存序列化对象编码的列也是UTF-8

问题是该对象包含一个包含法语字符的文本字符串。

例如:

Merci d'avoir passé commande avec Lovre. Voici le récapitulatif de votre commande 

当我序列化对象然后再次直接取消序列化它时,字符串被维护并且格式正确。

但是,当我将序列化对象存储到 MySql 数据库中然后再次检索它然后取消序列化它时,字符串变成这样:

Merci d'avoir passé commande avec Lovre. Voici le récapitulatif de votre commande 

将对象存储在数据库中时出现问题。

笔记:

  • 该对象使用 propel ORM 存储。
  • 列类型为text
  • 该字符串被存储并从 html 文件中读取。
4

4 回答 4

16

创建的字符串serialize是二进制字符串,它们没有特定的字符集编码,而只是一个字节“数组”(其中一个字节是 8 位,一个八位字节)。

如果您现在获取这样一个字符串并告诉您的数据库它是 LATIN-1 编码的,并且您的数据库将其存储到具有 UTF-8 编码的文本字段中,那么数据库将透明地将编码从 LATIN-1 更改为 UTF-8。UTF-8 是一种字符集编码,对于某些字符,每个字符使用一个以上字节,例如您在问题中给出的字符,例如é.

然后将该字符é存储é在数据库中,即é.

如果您现在从数据库中获取数据而没有指定您需要的编码,那么数据库会将其返回为 UTF-8。

现在unserialize有一个问题,因为二进制字符串已被修改为使其无效。

相反,您需要告诉您的数据库它在存储序列化字符串时不应修改编码,例如通过选择正确的列类型和编码(二进制字段,BLOB - Binary Large Object MySQL Docs,另见Binary Types Propel Docs ) - 或者 - 当您从数据库中获取数据时,您会将字符集编码恢复为原始格式。第一种方法(二进制字段)更好,因为它正是您正在寻找的。

对于已经以错误格式存入数据库的数据,需要更正数据。为此,您首先需要找出应用了哪种重新编码,例如从哪个字符集到哪个字符集。我认为它是 LATIN-1,但不能保证。您需要查看当前应用程序数据和流程的编码以找出答案。

找到后,将值从 UTF-8 编码回原始编码。

于 2012-02-02T09:10:10.147 回答
5

确保在任何地方都使用 utf-8 - 听起来你错过了一些东西。

在您的情况下,我认为您忘记为您的数据库连接设置正确的字符集(使用SET NAMES语句或mysql_set_charset())-但是如果没有看到您的代码就很难说(而且我不知道推进)。

以下是来自chazomaticus的引述,他一直在UTF-8中给出了完美的答案,列出了您必须注意的所有要点:

贮存:

  • utf8_unicode_ci对数据库中的所有表和文本列指定(或等效)排序规则。这使得 MySQL 在物理上以 UTF-8 本地存储和检索值。

恢复:

  • 在 PHP 中,无论您使用什么 DB 包装器,都需要将连接字符集设置为 utf8。这样,当 MySQL 将数据交给 PHP 时,它不会从其原生 UTF-8 进行转换。* 请注意,如果您不使用数据库包装器,您可能必须发出一个查询来告诉 MySQL 以 UTF-8 格式为您提供结果:(SET NAMES 'utf8' 一旦您连接)。

交货:

  • 您必须告诉 PHP 将正确的标头传递给客户端,因此文本将被解释为 UTF-8。在 PHP 中,您可以使用default_charset php.ini 选项,或者自己手动发出 Content-Type标头,这只是更多的工作但具有相同的效果。

提交:

  • 您希望浏览器发送给您的所有数据都采用 UTF-8 格式。不幸的是,可靠地做到这一点的唯一方法是将 accept-charset属性添加到所有 <form>标签:<form ... accept-charset="UTF-8">.
  • 请注意,W3C HTML 规范说客户端“应该”默认以服务器提供的任何字符集将表单发送回服务器,但这显然只是一个建议,因此需要在每个<form>标签上都明确。
  • 尽管在这方面,您仍然希望在尝试将每个提交的字符串存储或在任何地方使用它之前验证其是否为有效的 UTF-8。PHP mb_check_encoding()可以解决问题,但您必须虔诚地使用它。

加工:

  • 不幸的是,这是困难的部分。您需要确保每次处理 UTF-8 字符串时都是安全的。最简单的方法是广泛使用 PHP 的mbstring扩展。
  • PHP 的字符串操作默认不是 UTF-8 安全的。有些事情你可以安全地使用普通的 PHP 字符串操作(如连接),但对于大多数事情,你应该使用等效的mbstring函数。
  • 要知道你在做什么(阅读:不要搞砸了),你真的需要知道 UTF-8 以及它是如何在尽可能低的级别上工作的。查看来自utf8.com的任何链接,以获得一些很好的资源来学习您需要知道的一切。
  • 另外,我觉得这应该在某个地方说,即使它看起来很明显:您将提供的每个 PHP 或 HTML 文件都应该以有效的 UTF-8 编码。

请注意,您不需要使用 utf-8 - 重要的部分是在任何地方都使用相同的字符集,而与可能的字符集无关。但是,如果您无论如何都需要更改内容,请使用 utf-8。

于 2012-02-02T08:31:58.537 回答
2

我总是通过 using 存储 esrialized 数据base64_encode()。序列化数据有时会引起问题,但在使用它的 base64 值后,只剩下简单的字符。

于 2012-02-02T08:33:32.127 回答
1

我强烈建议您使用json_encode而不是序列化。有一天,您会发现自己试图使用来自 PHP 以外的其他地方的数据,并将其存储在 JSON 中使其在任何地方都可读;几乎每种语言都支持解码 JSON,并且是一个成熟的标准。

到处使用 utf8 的答案是成立的!:-D

于 2015-08-21T17:55:11.990 回答