在MySql数据库中存储序列化对象

时间:2012-02-02 08:21:35

标签: php mysql encoding propel object-serialization

我有一个很大的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 个答案:

答案 0 :(得分:11)

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) - 或者 - 从数据库中获取数据时,将charset-encoding恢复为原始格式。第一种方法(二进制字段)更好,因为它正是您正在寻找的。

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

在您发现之后,将值从UTF-8编码回原始编码。

答案 1 :(得分:4)

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

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

以下是来自chazomaticus的引用,她在 UTF-8 all the way through 中给出了完美答案,列出了您需要处理的所有要点:

  

存储

     
      
  • 指定utf8_unicode_ci(或   等价)所有表格的整理   和数据库中的文本列。   这使得MySQL物理存储和   以UTF-8原生检索值。
  •   
     

检索:

     
      
  • 在PHP中,在任何DB包装器中   使用,你需要设置连接   字符串到utf8。这样,MySQL就可以了   没有从其原生UTF-8转换   当它将数据移交给PHP时。   *   请注意,如果您不使用数据库   包装,您可能不得不发布   一个查询告诉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规范说明了这一点   客户“应该”默认发送   无论如何形成回服务器   charset服务器服务,但这是   显然只是一个推荐,   因此需要明确   每个<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 - 重要的部分是使用相同的charset无处不在,而不管可能是什么字符集。但如果你还需要改变一些东西,请使用utf-8。

答案 2 :(得分:1)

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

答案 3 :(得分:1)

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

关于在任何地方使用utf8的答案都有! :-D