Doctrine 2.3 - 由于特殊字符,不保存文本字段

时间:2013-04-18 09:21:32

标签: mysql character-encoding doctrine-orm symfony-2.1

我花了好几个小时调试一个算法并发现它来自Doctrine(v2.3.3)。 我正在使用libpuzzle来计算图像的哈希并将此哈希存储在数据库中。 返回的哈希中有特殊字符,显然Doctrine不喜欢它。

这是我拥有的那种字符串(~550 char):

  

...ÿþÿÿþþþÿþÿþÿþþþÿþÿÿÿÿþþÿþÿÿÿþÿþÿþþÿþþÿÿÿþÿþþþþÿþþþþÿÿÿÿÿþþÿþÿþÿþÿþþÿþÿÿÿþþÿþþþþÿþþþþÿÿÿþþþÿÿþþþÿÿþÿþþÿþþþÿþ

我调查过并发现有些人说要在配置中添加字符集,但我已经拥有它了:

# Doctrine Configuration
doctrine:
    dbal:
        driver:   "%database_driver%"
        host:     "%database_host%"
        port:     "%database_port%"
        dbname:   "%database_name%"
        user:     "%database_user%"
        password: "%database_password%"
        charset:  UTF8

如果我将列的排序规则从utf8_unicode_ci更改为utf8_general_ci仍然无法正常工作。此外,我确保默认架构排序规则为utf8_general_ci

我尝试过另一个带有特殊字符的字符串:

  

测试!§$%& /()=? äöüÄÖÜ:D

此字符串已正确插入但哈希仍然没有。

有谁知道我可以在哪里解决这个问题?这是一个学说错误吗?

----------------------------------

更新

在执行之前,我仍然拥有正确的数据绑定。所以我猜这是一个编码或驱动程序问题。我修改了symfony配置:

# Doctrine Configuration
doctrine:
    dbal:
        driver:   "%database_driver%"
        host:     "%database_host%"
        port:     "%database_port%"
        dbname:   "%database_name%"
        user:     "%database_user%"
        password: "%database_password%"
        charset:  UTF8
        options:
            1002: "SET NAMES 'UTF8'"

我还试图在不使用实体的情况下执行查询:

$this->db = $this->getContainer()->get('doctrine')->getConnection();

$img = '/var/www/acme/web/upload/tmp/cd1fa593cf6feb2cde83e68f461a2d947.jpg';
$hash = puzzle_fill_cvec_from_file($img);

$sql = "UPDATE image set hash=? WHERE id=?";
$stmt = $this->db->prepare($sql);

$stmt->execute(array($hash, 180));

数据库中仍为空数据。 在另一个项目中,我使用了Zend_Db并且在保存此哈希时没有任何问题。 我不知道这是Doctrine中的错误:(

----------------------------------

更新2

我已经在mysql中记录了所有查询,我可以在日志中看到内容绑定正确。但是没有被mysql正确保存。

INSERT INTO image (guid, type, createTime, updateTime, images, imageSize, imageHash, status) 
VALUES (
'c30df23d6b0b08aff079287e00f21ec8a', 
'image', 
'2013-04-22 03:30:33', 
'2013-04-22 03:30:34',
'path/image.jpg', 
'165458', 
'?\0????\0?????????\0??????\0??????\0??????????????????????\0????\0??\0???\0???????????????????????????\0\0\0??\0?\0??\0??????????????????\0\0\0??\0?\0???????????????\0?????????????????\0?\0????????????\0?\0??????????????????????????\0?\0???????????\0???\0?????????\0??????\0\0?????????????????????\0\0??????\0???????????????\0', 
1)

这是我的创建表:

delimiter $$
CREATE TABLE `image` (
  `id` bigint(20) NOT NULL AUTO_INCREMENT,
  `guid` varchar(255) COLLATE utf8_unicode_ci NOT NULL,
  `type` varchar(255) COLLATE utf8_unicode_ci NOT NULL,
  `createTime` datetime NOT NULL,
  `updateTime` datetime DEFAULT NULL,
  `images` varchar(255) COLLATE utf8_unicode_ci DEFAULT NULL,
  `imageSize` bigint(20) DEFAULT NULL,
  `imageHash` longtext COLLATE utf8_unicode_ci,
  `status` integer(10) NOT NULL,
  PRIMARY KEY (`id`)
) ENGINE=InnoDB DEFAULT CHARSET=utf8 COLLATE=utf8_unicode_ci$$

干杯, 马克西姆

2 个答案:

答案 0 :(得分:2)

你不应该使用imageHash longtext COLLATE utf8_unicode_ci, 因为RDBM会尝试将数据映射到字符集,如果你的哈希数据是libpuzzle二进制输出,这显然不匹配。

尝试更改您的架构,使imageHash列成为BLOB

如上所述:http://dev.mysql.com/doc/refman/5.0/en/blob.html

BLOB值被视为二进制字符串(字节字符串)。它们具有无字符集,并且排序和比较基于列值中字节的数值。

TEXT值被视为非二进制字符串(字符串)。它们具有字符集,并且值将根据字符集的排序规则进行排序和比较

答案 1 :(得分:0)

默认情况下,您的MySQL服务器可能未配置为从客户端接受UTF8。

在这种情况下,您需要运行以下查询:

SET NAMES utf8

在PHP脚本的开头运行它,例如通过Doctrine Connection对象。