2012-02-02 92 views
8

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

问题是该对象拥有包含法文字符的文本字符串。

例如:

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 

出了差错。

注:

  • 的目的是使用推进ORM存储。
  • 列类型为text
  • 该字符串存储并从html文件中读取。
+0

你的文件的编码是什么? – alexn 2012-02-02 08:23:02

+0

你可以尝试base_64编码,但你不应该那样做。数据库列是什么类型?你有没有在php中检查数据库连接设置? – 2012-02-02 08:23:40

+0

@TheSilencer数据库列的类型是文本。数据库连接使用PROPEL完成。 – Songo 2012-02-02 08:27:25

回答

10

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

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

然后将字符é作为é存储在数据库内,这是针对é的UTF-8字节序列。

如果您现在从数据库中获取数据而不指定您需要的编码,数据库将以UTF-8形式返回。

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

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

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

找到之后,将UTF-8中的值编码为原始编码。

+0

我尝试了你所说的并将列类型转换为BLOB,但问题仍然存在。但是,我决定在从数据库中检索对象后自己对消息进行'utf_decode'解决这个问题。 – Songo 2012-02-02 10:03:36

+0

它是否存在现有数据和/或新数据?此外,我不是推进专家,但我非常肯定,数据库层必须有一个直接的解决方案,因此您不需要关心应用程序逻辑代码中的编码。如果你解决不了的数据库层上,也有在PHP中['Serializable'(http://php.net/Serializable)接口,它可能会有所帮助,让您的代码更干净。 – hakre 2012-02-03 10:34:17

+0

我没有现有数据,因为我仍处于开发阶段。我检查了PROPEL配置,它在连接中使用UTF-8。也许有些东西我错过了,但是我会研究你提到的Serializable接口。谢谢你的帮助。 – Songo 2012-02-03 23:29:04

4

请务必使用utf-8 无处不在 - 听起来像你错过了什么。

你的情况

,我想你已经忘记设置正确的字符集为你的数据库连接(使用SET NAMES陈述或mysql_set_charset()) - 但那是很难没有看到你的代码的说(我不知道推动)。

以下是chazomaticus报价,谁在UTF-8 all the way through给了一个完美的答案,列出所有你要照顾点:

存储:

  • 指定utf8_unicode_ci(或 等效)整理所有表 和数据库中的文本列。 这使得MySQL实际存储并且 本地以UTF-8检索值。

检索:

  • 在PHP中,无论DB包装你 使用,你需要连接 字符集设置为UTF-8。这样,当MySQL将数据交给PHP时,它不会从其原生UTF-8 转换为 。 * 需要注意的是,如果你不使用DB 包装,你可能必须发出一个 查询告诉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。

1

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

1

我强烈建议您使用json_encode而不是序列化。有一天,你会发现自己试图从另一个不是PHP的地方使用这些数据,并且它以JSON存储,使得它到处都是可读的;几乎所有的语言都支持解码JSON并且是一个很好的标准。

关于使用utf8到处的答案持有! :-D

+0

不是个好主意:1。它将数组转换为对象,2.类的类型和方法丢失 – 2016-08-25 06:13:26

+0

方法丢失了......你不用'serialize'调用保存它们 相信我,对于存储序列化的东西来说是一个糟糕的主意。你最终需要从其他地方阅读这些东西。 如果需要反序列化回一类只存储类型为字符串并切换事后实例化JSON数据正确类的领域和回访平原JSON,像任何ORM基本上没有对数据库记录。 – 2016-09-16 15:51:52