【问题标题】:PDO cutting off strings at a UTF-8 character [duplicate]PDO 以 UTF-8 字符截断字符串 [重复]
【发布时间】:2014-05-15 17:14:51
【问题描述】:

我使用的是 PHP 5.5,当我尝试在 MySQL 数据库中插入 UTF-8 字符时,PDO 在第一个非 ASCII 字符处将其截断。

我已将连接设置为:

(DB_TYPE.':host='.DB_HOST.';dbname='.DB_NAME.';charset=utf8', DB_USER, DB_PASS, array(PDO::ATTR_DEFAULT_FETCH_MODE => PDO::FETCH_ASSOC, PDO::ATTR_ERRMODE => PDO::ERRMODE_WARNING))

我已经尝试了每个人都发布的 SET NAMES,但这也不起作用,因为问题不在 MySQL 方面。

当我通过 phpMyAdmin 并直接从 MySQL 控制台进行插入时,它可以工作! 当我使用 PDO 选择重音字符串时,它可以工作!

问题仅出现在 INSERTUPDATE 专门使用 PDO 上!

这是表的SQL。全部都是 UTF-8,但也许有人知道设置和 PDO 之间存在冲突

CREATE TABLE IF NOT EXISTS `mytable` (
  `id` int(11) NOT NULL AUTO_INCREMENT,
  `id_lang` int(11) NOT NULL DEFAULT '2',
  `id_tgroup_cat` int(11) NOT NULL,
  `fieldfor` int(11) NOT NULL,
  `colors` varchar(100) NOT NULL,
  `text` text NOT NULL,
  PRIMARY KEY (`id`)
) ENGINE=InnoDB  DEFAULT CHARSET=utf8 AUTO_INCREMENT=34 ;

我已经尝试将 text 设为 varchar 字段,但这并没有改变任何内容。

PHP 中的实际插入:

    $query = $this->db->prepare("UPDATE mytable
                                    SET text = ?,
                                        colors = ?
                                    WHERE id = ?");
    $query->execute(array($text, $colors, $id));

其中$text = "référence"(仅将字母 R 保存在数据库中,但没有重音符号它会保存所有内容),$colors 是用于测试目的的空字符串,$id2

【问题讨论】:

  • var_dump($text) 产生string(11) "référence"?
  • 是的,确实如此。
  • 在该问题上也尝试过解决方案@MarcusAdams - 没有成功。不过,杰克可能会有所作为。

标签: php mysql pdo


【解决方案1】:

这是我的关键线索:

其中 $text = "référence"(仅将字母 R 保存在数据库中,但 没有重音,它可以保存所有内容)并且 $colors 是一个空字符串 用于测试目的,$id 为 2。

听起来像是 UTF-8 编码问题。虽然数据库是 UTF-8,但从代码到数据库的整个链(包括连接)应该是 UTF-8 干净的。

$this->db->prepare 与 PHP 到 MySQL 的连接到底有什么关系?您显示的代码有点不清楚。但根据您所展示的内容,也许像这样调整您的查询会有所帮助:

$query = $this->db->prepare("SET collation_connection = utf8_bin;
                             SET NAMES utf8;
                             UPDATE mytable
                                SET text = ?,
                                    colors = ?
                                WHERE id = ?");

或者这样:

$this->db->exec("SET collation_connection = utf8_bin; SET NAMES utf8;");
$query = $this->db->prepare("UPDATE mytable
                                SET text = ?,
                                    colors = ?
                                WHERE id = ?");

注意我强制添加了SET collation_connection = utf8_bin;SET NAMES utf8;

通常,您需要确保从连接到数据库再到表的整个链都是 UTF8 干净的。我对a similar question here有详细的答复。

但在您的情况下,请检查实际的 MySQL 服务器 my.cnf 文件。以下会将整个链设置为 UTF-8:

[client]
default-character-set=utf8

[mysql]
default-character-set=utf8

[mysqld]
collation-server = utf8_unicode_ci
init-connect='SET NAMES utf8'
character-set-server = utf8

编辑: 由于原始海报表明数据来自 HTML5 表单,我还认为检查实际 HTML5 文件本身的 BOM(字节顺序标记)也会有所帮助。它应该设置为 UTF8。有关what a BOM is are over here 的更多详细信息。特别是 Martin Code 接受的答案,其中解释了:

UTF-8 BOM 是一个字节序列 (EF BB BF),允许阅读器 将文件识别为 UTF-8 文件。

【讨论】:

  • 如 OP 中所述,这不起作用(并且有更好的方法可以通过 PDO 做到这一点) - 这显然是 utf8 不匹配 - 我只需要弄清楚在哪里以及为什么:)
  • @MrJack 请检查我的最新编辑。如果这没有帮助,那就够公平了。但是您的帖子中缺少的一件事是清楚地说明了首先设置这些字符串的位置。它们来自一个表格吗?文件是否与 BOM 一起保存为 UTF8?这方面的更多细节会有所帮助。
  • 好的,通过将文件删除并重新创建为 utf8 来让它工作
  • 我在 Ubuntu 12.04 上。它仍然没有 BOM,但现在它保存了,所以这一切都很重要。不过,我是从一个复制的文件开始工作的,所以可能一开始就设置有问题。
  • @MrJack “不过,我是从一个复制的文件开始工作的,所以可能一开始就设置有问题。”答对了!如果您直接从 Windows 机器或从肯定会导致该问题的存档中获取文件。
猜你喜欢
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2012-09-11
  • 1970-01-01
  • 2014-06-09
相关资源
最近更新 更多