Mojoliciousで文字化けが起こった時の対処法2つ

PerlのMVSフレームワーク「Mojolicious」を使っていて、$c->renderでHTMLを表示した時に日本語が文字化けしたので、その対処法を2つ紹介していきます。

そもそもPerlで文字化けが起こる原因とは?

そもそも、Perlで文字化けが起こる原因とは何でしょうか?

起こりうる原因は色々ありますが、多くの場合は「内部文字列」と「バイト文字列」の誤った扱いによる所が多いです。

バイト文字列とは、簡単に言うと「文字コード」の事ですね。文字を扱う上で基本になるのが文字コードですが、こんにちわと言う文字の長さが15(utf8の場合)と出たりする等、プログラムをする時に直感的に理解できる処理にならない、と言う欠点があります。

そう言う通常の文字コードの欠点を補ったのが、Perl独自の「内部文字列」と言うやつ。

基本的にutf8と同じ動作をしますが、こんにちわの文字列の長さが5になる等、プログラムを組むのに理解しやすい処理をしてくれます。

ただ、Perlの内部文字列はPerl独自の物なので、ファイル操作とかDB操作(DBIやMySQL操作)の外部プログラムとのやり取りで文字列を扱う時に、不自然な挙動をし始めるのが文字化けの原因です。

(今回の記事では内部文字列と言う表記をしていますが、他のネットの記事や本によっては、「テキスト文字列」「内部表現」「Perl文字列」と言う表現をしている場合もあります。)

また、Perlの内部文字列については以下の記事が詳しいです。

参考:第16回 Perl内部構造の深遠に迫る(2):Perl Hackers Hub|gihyo.jp … 技術評論社

参考:Perl の文字列エンコーディングの話 | Hachioji.pm 日めくりテックトーク

Mojoliciousで文字化けが起こった時の対処法2つ

実際にMojolicousで文字化けが起こった場合の対処法には、以下の2つがあります。

1, DBIのオプションにmysql_enable_utf8 => 1をつける

PerlのデータベースのモジュールとしてDBIを使っている場合は、mysql_enable_utf8 => 1のオプションをつける事で簡単に解決できます。

実装方法は簡単で、DBI->connectの第4引数にオプションとして付けるだけです。今回の例ではMySQLにしていますが、他のDBでもできるはずです。(調べていない)

    DBI->connect( "DBI:mysql:database=sample;host=localhost",
        "root", "pass", { mysql_enable_utf8 => 1 } )
      or die $DBI::errstr;

また、DBI関連で調べる時は、perl DBIとググるだけでなく、perl DBI myslqのようにそれぞれのDBで調べた方が調べたい事がよく出てきます。

参考:DBD::mysql - MySQL driver for the Perl5 Database Interface (DBI) - metacpan.org

Encodeモジュールのdecodeメソッドを使う

PerlにはEncodeモジュールと言うものがあって、そのdecodeメソッドを使うと文字化けが解決できます。

例えば、以下のようにコントローラー内にindexメソッドを定義しているとします。以下の例では$c->stash( str => $str );で$str変数をテンプレートに渡していますが、このままでは文字化けしてしまうとします。

sub index {
    my $c      = shift;
    my $str = $c->post_db->find;
    $c->stash( str => $str );
    $c->render;
}

しかし、以下のようにdecodeをして、普通の文字列をPerlの内部文字列に変える事で文字化けを防ぐ事ができます。

use Encode;

sub index {
    my $c      = shift;
    my $str = $c->post_db->find;
    $str = decode('utf8', $str);
    $c->stash( str => $str );
    $c->render;
}