Hatena::ブログ(Diary)

ぬかるむ日々

2007-12-15

[][]Akelosmysql文字化けをどうにかする 17:09 Akelosでmysqlの文字化けをどうにかするを含むブックマーク

Akelos+mysql4.1以降の組み合わせでデータベースで日本語を扱う場合、mysql文字コードの設定次第で文字化けしする。というかこれはakelosに限った話ではなくて、mysql4.1以降の場合「SET NAMES xxx」を実行しておかないと文字コードが正しく扱われない。

ということで今まで「application_controller.php」に以下のようにbeforeFilterを書いて対応させてたけど、、、

<?php
class ApplicationController extends AkActionController 
{
  function __construct()
  {
    $this->beforeFilter('_setDbEncoding');
  }
  
  function _setDbEncoding()
  {
    $db =& Ak::db();
    $db->Execute('SET NAMES utf8');
  }
}

これだと、うまくいかないケースがあったのでAkelosのソースに直接処理を追加することにした。

ほぼすべてのケースでADODBのシングルトンインスタンスAk.phpAk::db()で呼び出されるので、該当部分を探して以下のように処理を追記。

akelos_framework/lib/AkActiveRecord/AkDbAdapter.php

<?php
// 52行目付近
    function connect()
    {
        $dsn = $this->_constructDsn($this->settings);
        require_once(AK_CONTRIB_DIR.DS.'adodb'.DS.'adodb.inc.php');
        $this->connection = AK_DEBUG ? NewADOConnection($dsn) : @NewADOConnection($dsn);
        if (!$this->connection){
            error_reporting(E_ALL);
            if(defined('AK_DATABASE_CONNECTION_FAILURE_CALLBACK') && function_exists(AK_DATABASE_CONNECTION_FAILURE_CALLBACK)){
                $fn = AK_DATABASE_CONNECTION_FAILURE_CALLBACK;
                $fn();
            }
            if(!AK_PHP5 && $this->type() == 'sqlite'){
                trigger_error(Ak::t("\nWarning, sqlite support is not available by default on PHP4.\n Check your PHP version by running \"env php -v\", and change the first line in your scripts/ so they point to a php5 binary\n\n"),E_USER_WARNING);
            }
            trigger_error(Ak::t("Connection to the database failed. %dsn",
            array('%dsn'=> AK_DEBUG ? preg_replace('/\/\/(\w+):(.*)@/i','//$1:******@', urldecode($dsn))."\n" : '')),
            E_USER_ERROR);
        } else {
            $this->connection->debug = AK_DEBUG == 2;
            // ↓Mysql 文字化け対応追加
            if($this->type() == 'mysql' && preg_match('/[\?&]encoding=(\w+)/', urldecode($dsn), $found))
            {
              $this->connection->Execute('SET NAMES '.$found[1]);
            }
            // ↑ここまで
            $this->connection->SetFetchMode(ADODB_FETCH_ASSOC);
            defined('AK_DATABASE_CONNECTION_AVAILABLE') ? null : define('AK_DATABASE_CONNECTION_AVAILABLE', true);
        }
    }

あとは、アプリケーションの設定ファイルでデータベース設定に「encoding=xxx」を追加すればいい。

config/config.php

<?php
// データベース設定
$database_settings = array(
  'development' => array(
     'type' => 'mysql',
     'database_file' => '',
     'host' => 'localhost',
     'port' => '',
     'database_name' => 'app_dev',
     'user' => 'username',
     'password' => 'password',
     'options' => 'encoding=utf8' // ← encodingを追加
  ),
);

ひとまずこれで文字化けは発生しなくなったけど、ベータの内からソースはあんまり弄りたくないのが本音。

トラックバック - http://d.hatena.ne.jp/simpraight/20071215