#前に社内wikiに書いておいたのを公開してみるテスト。

追記: この情報は若干古いです。ここを読んだ後にこちら読むと良いです。

Catalystでマルチバイトを扱う機会があるのは主に
  • ユーザーがフォームで入力する値 ($c->req->param())
  • データベースからの入出力 (DBIx::Class)
  • それ以外の文字列の評価
  • View::TTによる出力の生成
  • FillInFormによるフォームの埋め込み
  • HTTPレスポンス
です。 ここでは以下の条件でまとめてみました。
  • 文字コードはUTF8に統一
  • データベースにはmysqlを使用

下準備

テンプレート、perlのコードは全てUTF8で書きます。

mysqlの文字コードの指定は/etc/my.cnfに

[mysqld]
default-character-set = utf8
skip-character-set-client-handshake
[mysql]
default-character-set = utf8
[mysqldump]
default-character-set = utf8

を書いてから起動して、create databaseします。

ユーザーがフォームで入力する値 ($c->req->param())

Catalyst::Plugin::Unicodeを使う。 prepare_parameters時に$c->req->paramsの値にutf8フラグを立ててfinalize時に$c->res->bodyからutf8フラグを落としてくれる。

ただしfinalizeメソッドをオーバーライドしているのでFillInFormなどを使う場合には

use Catalyst qw/
	...
	FillInForm
	...
	Unicode
/;

とかして最後にロードするようにする。
(via http://unknownplace.org/memo/2006/03/09#e004)

データベースからの入出力 (DBIx::Class)

DBIx::Class::UTF8Columnsを使う。 $row->get_column/get_columnsでutf8フラグを立てて返す。
__PACKAGE__->load_components(qw/UTF8Columns Core/);
__PACKAGE__->utf8_columns(qw/name description/);

とかするとutf8_columnsで指定した$row->nameや$row->descriptionにutf8フラグが立つ。
指定していないものにはutf8フラグは立っていないのでマルチバイトコードを扱いそうなカラムは全部指定した方が良いかも。

それ以外の文字列の評価

常にutf8フラグを立てて評価する。
utf8::decode($str);

View::TTによる出力の生成

Catalyst::View::TT::ForceUTF8を使う。 テンプレートをutf8フラグを立てて処理する。
script/create.pl view TT TT::ForceUTF8

でViewクラスを作るか

すでにあるMyApp::View::TTを

use base 'Catalyst::View::TT::ForceUTF8';

として継承関係を変ればOK。

FillInFormによるフォームの埋め込み

通常は上記のことだけでOKなのですが、まれに
$c->req->param->{name} = 'ほげ';

というような処理をする場合、当然この文字列にはutf8フラグが立っていないのにView::TT::ForceUTF8でレンダリングされたutf8フラグ付きの文字列にfillformしようとするため文字化けします。

対処方法としては、"・それ以外の文字列の評価"で説明したとおり、常にutf8フラグを立てて取り扱えばいいのですが、面倒なときもあるのでHTML::FillInForm::ForceUTF8を使ったCatalyst::Plugin::FillInForm::ForceUTF8ってのを作りました。これだとfillform時に全てutf8フラグを立てるので文字化けは起こらなくなります。
ついでにFV::Sとか使ってると勝手にfillinするおせっかいな処理を抑制するオプション付き。

MyApp->config->(
    fillinform->{
        auto => 0
    }
);

HTTPレスポンス

HTTPレスポンスのcontent-typeはCatalystではデフォルトでutf8が設定されるけど、明示的に指定したい場合はMyApp::Controller::Rootで
sub render : ActionClass('RenderView'){}

sub end : Private{
	my ($self, $c) = @_;

	$c->forward('render');
	$c->res->content_type("text/html; charset=utf8");
}

とかしておけばOK。

              

              

トラックバック(2)

トラックバックURL: http://mt.hide-k.net/mt-tb.cgi/645

PukiWiki/TrackBack 0.2 - Perl/Catalyst/日本語 (2008年8月12日 17:28)

Perl/Catalyst 概要 入力部分 ユーザーがフォームで入力する値 ($c->req->param()) デー... 続きを読む

以前、Catalystでマルチバイトを取り扱うときのまとめという記事を書いたのですが、情報が少し古いので、最近僕がやっている方法を紹介します。 この記事... 続きを読む

コメントする

プロフィール

このブログ記事について

このページは、hideが2007年3月26日 18:57に書いたブログ記事です。

ひとつ前のブログ記事は「最近買ったHouse remixなCDS」です。

次のブログ記事は「ナイトミュージアム」です。

最近のコンテンツはインデックスページで見られます。過去に書かれたものはアーカイブのページで見られます。