【问题标题】:Doctrine 2.3 - text field is not saved because of special charactersDoctrine 2.3 - 由于特殊字符,文本字段未保存
【发布时间】:2013-04-18 09:21:32
【问题描述】:

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

这是我拥有的那种字符串(约 550 个字符):

ÿ�þÿÿþ�þþÿþÿþÿþþ�þÿþÿÿÿ�ÿþþÿþÿ�ÿÿþÿþÿþþÿþþÿÿÿþÿþþþþÿþ�þþþÿ�ÿÿ�ÿÿþ�þÿþÿþÿþÿþþÿþÿÿÿþþÿþþþþÿþþþþ���ÿÿ�ÿ�þþ�þÿÿþþþÿÿþÿþþÿþþþÿþ...

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

# 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

这个字符串插入正确,但哈希仍然没有。

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

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

更新

就在执行之前,我仍然绑定了正确的数据。所以我猜这是编码或驱动程序问题。我已经修改了 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$$

干杯, 马克西姆

【问题讨论】:

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


    【解决方案1】:

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

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

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

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

    TEXT 值被视为非二进制字符串(字符串)。它们有一个字符集值会根据字符集的排序规则进行排序和比较

    【讨论】:

    • 如果我必须在此列中存储不同的字符串怎么办?例如,现在我正在使用 libpuzzle 来获取图像签名,但如果我更改算法,我可能会有一个常规字符串或只有一个整数等......这会是问题还是性能问题(使用 blob)?跨度>
    • TEXTLONGTEXT 在我的情况下被视为 BLOB 并以相同的方式存储:dev.mysql.com/doc/refman/5.0/en/blob.html
    • 你看过我的回答了吗?我刚刚对其进行了更新,以将重要部分添加到 bold 中。
    • 顺便说一句,我确实阅读了您指向的链接,我什至把它放在我的答案中。这就是我得到上述声明的地方。
    • 所以,真的,你应该试试 BLOB。因为它确实表现得像 TEXT。
    【解决方案2】:

    可能是您的 MySQL 服务器未配置为默认接受来自客户端的 UTF8。

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

    SET NAMES utf8
    

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

    【讨论】:

    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2013-02-22
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多