Zend_Db_Table_Row,Zend_Db_Table_Rowsetで日本語(文字化け)エンコード変換  2009年6月4日

Bsheもそうですが、私は最近PHPのプログラムのエンコードはたいていUTF-8で書いています。

ですが、データベースは前のシステムとの兼ね合いなどでEUC-JPなどが利用されていることが多いため、Zend_Db_Table関係を少し機能追加して、Zend_Db_Table_RowクラスとZend_Db_Table_RowsetクラスにtoArrayの他にtoMbArrayメソッドを追加してみました。

配列適用用のコード変換関数を用意

array_walkから呼び出す用の以下の関数を用意しておきます。

function arrayMbConvertEncoding(&$item, $key, $arrayConfig)
{
    $toEncoding = $arrayConfig[0];
    $fromEncoding = $arrayConfig[1];
    if (is_string($item)) {
        $item = mb_convert_encoding($item, $toEncoding, $fromEncoding);
    }
}

Zend_Db_Tableクラスを拡張

Dbクラスで保持して、テーブルクラスではDbクラスからの値を取得してもいいと思いますがここでは、Dbのエンコードをテーブルクラスで保持するようにします。

class Cshe_Db_Table extends Zend_Db_Table
{
    /**
     * DBのエンコーディング
     *
     * @var unknown_type
     */
    protected $dbEncoding;

    /**
     * mainDBの接続を自動設定するコンストラクタ
     *
     * @param config
     */
    public function __construct($config = null)
    {
        try {
            // DBエンコーディングセット
            if( isset( $config['db_encoding']))
            {
                $this->dbEncoding = $config['db_encoding'];
                unset( $config['db_encoding']);
            }
            // row,rowsetクラス設定
            $config['rowClass'] = ‘Cshe_Db_Table_Row’;
            $config['rowsetClass'] = ‘Cshe_Db_Table_Rowset’;

            // 親クラスのコンストラクタ
            parent::__construct($config);
        }
        catch(Exception $e)
        {
            throw $e;
        }
    }

    /**
     * Databaseのエンコーディングを設定する。
     */
    public function getDbEncoding()
    {
        return $this->dbEncoding;
    }
}

これで、テーブルクラスをインスタンス化するときに、以下のようにすることで、エンコードをセットできます。

$db = Zend_Db::factory(‘Pdo_Mysql’, array(
        ‘host’     => ‘*****’,
        ‘username’ => ‘*****’,
        ‘password’ => ‘*****’,
        ‘dbname’   => ‘*****’
        ));
$tbl = New Cshe_Db_Table(array(‘name’ => ‘*****’, ‘db’ => $db, ‘db_encoding’ => ‘***’));

Rowクラスを拡張

RowクラスにtoMbArray(toArrayにエンコード変換を加えたもの)メソッドを追加し、__getメソッドをオーバーライドします。

class Cshe_Db_Table_Row extends Zend_Db_Table_Row
{

    /**
     * エンコーディングをDBから、PHP内部エンコードに変更して返す
     *
     */
    public function toMbArray()
    {
        $toEncoding = ini_get( ‘mbstring.internal_encoding’);
        try {
            $arrayTmp = $this->toArray();
            array_walk_recursive($arrayTmp, ‘arrayMbConvertEncoding’, array($toEncoding, $this->_table->getDbEncoding()));
            return $arrayTmp;
        }
        catch( Exception $e)
        {
            throw $e;
        }
    }

    /**
     * getにマルチバイト対応を適用
     *
     */
    public function __get($columnName)
    {
        $toEncoding = ini_get( ‘mbstring.internal_encoding’);

        $columnName = $this->_transformColumn($columnName);
        if (!array_key_exists($columnName, $this->_data)) {
            require_once ‘Zend/Db/Table/Row/Exception.php’;
            throw new Zend_Db_Table_Row_Exception("Specified column \"$columnName\" is not in the row");
        }
        return mb_convert_encoding( $this->_data[$columnName], $toEncoding, $this->_table->getDbEncoding());
    }
}

Rowsetクラスを拡張

RowsetクラスにtoMbArray(toArrayにエンコード変換を加えたもの)メソッドを追加します。

class Cshe_Db_Table_Rowset extends Zend_Db_Table_Rowset
{

    /**
     * エンコーディングをDBから、PHP内部エンコードに変更して返す
     *
     */
    public function toMbArray()
    {
        $toEncoding = ini_get( ‘mbstring.internal_encoding’);
        try {
            $arrayTmp = $this->toArray();
            array_walk_recursive($arrayTmp, ‘arrayMbConvertEncoding’, array($toEncoding, $this->_table->getDbEncoding()));
            return $arrayTmp;
        }
        catch( Exception $e)
        {
            throw $e;
        }
    }
}

これで、以下のようにすると、文字コードを変換したデータをRowsetから取得できるようになります。

$db = Zend_Db::factory(‘Pdo_Mysql’, array(
        ‘host’     => ‘*****’,
        ‘username’ => ‘*****’,
        ‘password’ => ‘*****’,
        ‘dbname’   => ‘*****’
        ));
$tbl = New Cshe_Db_Table(array(‘name’ => ‘*****’, ‘db’ => $db, ‘db_encoding’ => ‘***’));

$rowset = $tbl->fetchAll();
$arraytmp = $rowset->toMbArray();

 

このエントリをはてなブックマークに登録 このエントリをBuzzurlにブックマーク Yahoo!ブックマークに登録 このエントリをlivedoorクリップに登録 Deliciousにブックマーク

コメントを投稿