|
在数据库驱动的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 |
评分
-
查看全部评分
|