用户
 找回密码
 入住 CI 中国社区
搜索
查看: 9455|回复: 1
收起左侧

[插件 Plugin] Codeigniter + Doctorine出现Mysql中文乱码的解决方案

  [复制链接]
发表于 2010-8-2 18:00:33 | 显示全部楼层 |阅读模式
在数据库驱动的WEB应用中出现中文乱码,绝大多少都是由于数据库和程序字符编码不一致造成的。

在很多PHP应用中,我们使用开源ORM框架Doctrine来给应用程序添加一个数据抽象层(Data Abstract Layer),以此完善和丰富分层的程序架构。在Codeigniter中,我们可以以插件(Plugins)的形式将Doctrine完美的嵌入到CI应用中,PHPandStuff上有一个系列教程专门教大家解决这个问题,这里我就不再赘述。

需要注意的是,如果直接使用PHPandStuff教程提供的Plugin配置源代码开发中文网站,可能会出现中文乱码问题。这是由于它没有指定数据库字符集。为了解决这个问题,我们需要做个小的修改。

打开application/plugins/doctrine_pi.php,找到链接数据库的地方,在其之后添加如下两行:

PHP复制代码
// 因为使用的是Doctorine ORM,所以config/database.php中设置的DbCollate和Charset无效
// 需要在连接数据库成功之后,手动设置
// by Saturn
Doctrine_Manager::connection()->setCharset('utf8');
Doctrine_Manager::connection()->setCollate('utf8_general_ci');
 
复制代码


完整的doctrine_pi.php文件代码如下(部分代码由PHPandStuff原作者贡献):

PHP复制代码
// ------------------------------------------------
// system/application/plugins/doctrine_pi.php
// load Doctrine library
require_once APPPATH.'/plugins/doctrine/lib/Doctrine.php';
 
// load database configuration from CodeIgniter
require_once APPPATH.'/config/database.php';
 
// this will allow Doctrine to load Model classes automatically
spl_autoload_register(array('Doctrine', 'autoload'));
 
// we load our database connections into Doctrine_Manager
// this loop allows us to use multiple connections later on
foreach ($db as $connection_name => $db_values) {
 
 // first we must convert to dsn format
 $dsn = $db[$connection_name]['dbdriver'] .
  '://' . $db[$connection_name]['username'] .
  ':' . $db[$connection_name]['password'].
  '@' . $db[$connection_name]['hostname'] .
  '/' . $db[$connection_name]['database'];
 
 Doctrine_Manager::connection($dsn,$connection_name);
}
 
 
// 因为使用的是Doctorine ORM,所以config/database.php中设置的DbCollate和Charset无效
// 需要在连接数据库成功之后,手动设置
// by Saturn
Doctrine_Manager::connection()->setCharset('utf8');
Doctrine_Manager::connection()->setCollate('utf8_general_ci');
 
// CodeIgniter's Model class needs to be loaded
require_once BASEPATH.'/libraries/Model.php';
 
// telling Doctrine where our models are located
Doctrine::loadModels(APPPATH.'/models');
// (OPTIONAL) CONFIGURATION BELOW
 
// this will allow us to use "mutators"
Doctrine_Manager::getInstance()->setAttribute(
 Doctrine::ATTR_AUTO_ACCESSOR_OVERRIDE, true);
 
// this sets all table columns to notnull and unsigned (for ints) by default
Doctrine_Manager::getInstance()->setAttribute(
 Doctrine::ATTR_DEFAULT_COLUMN_OPTIONS,
 array('notnull' => true, 'unsigned' => true));
 
// set the default primary key to be named 'id', integer, 4 bytes
Doctrine_Manager::getInstance()->setAttribute(
 Doctrine::ATTR_DEFAULT_IDENTIFIER_OPTIONS,
 array('name' => 'id', 'type' => 'integer', 'length' => 4));
 
/* End of file doctrine_pi.php */
/* Location: ./system/application/plugins/doctrine_pi.php */
 
复制代码


在MySQL中,与字符编码相关的参数有:字符集(Character Set)和整理(collation)两个选项,对于每个数据库,这两个选项都可以根据需要分别制定。需要注意的是,Character Set和collation是存在联系的。具体的定义,联系和区别,我们可以参考stackoverflow上的解释,我觉得非常经典,简单来说:

字符集(Character Set)就是一系列符号和编码的组合;而整理(collation)则用来比较具体字符集的标准。

在Mysql中,如果我们不指定字符集和整理两个选项,程序会使用系统默认的字符集。而Mysql的默认字符集是lantin1,默认整理参数是latin1_swedish_ci。对于英文语系来说,这两个参数不会对数据的存储造成任何影响。但是对于其他字符集,特别是我们需要存储东亚字符(比如中文)时,我们最好手动在数据库和程序中分别指定相一致的字符编码,否则就会出现乱码的情况。

上例中所添加的两行代码就是在程序中指定字符集和整理为utf-8;为了彻底避免和解决乱码问题,你也应该确认数据库的字符集和编码与上面的设定相一致,也就是utf-8。

Update: mysql中允许你在3个不同级别对字符集进行指定,分别是:数据库(database)级,表(table)级和栏位(field)级。请确认你数据库中这三个级别的字符集相一致。

原文来自我的博客:http://www.cnsaturn.com/posts/61

评分

参与人数 1威望 +5 收起 理由
Hex + 5 精品文章

查看全部评分

发表于 2011-1-13 08:09:37 | 显示全部楼层
大哥,您好。我解决啦~但是还有一个问题。我去了Doctrine的官网下载ORM【DoctrineORM-2.0.0-full.tar.gz】发现解压之后里面根本就找不到lib文件夹。请问在哪里下载啊?(我现在都是在使用http://www.phpandstuff.com/ 这个网的源码项目拷个lib下来而已啊!)

本版积分规则