MENTAの練習で簡単な掲示板を作成しました。
MENTAの解凍とリネーム
下記の手順で解凍して、ディレクトリ名を変更します。
$ tar xvzf MENTA-0.15.tar.gz $ mv MENTA-0.15 simple_bbs $ cd simple_bbs
MySQLのセットアップ
下記のテーブルを作成しました。
CREATE TABLE `bbs` ( `id` int(11) NOT NULL AUTO_INCREMENT, `title` varchar(255) DEFAULT NULL, `message` text , `datetime` datetime DEFAULT NULL, PRIMARY KEY (`id`) ) ENGINE=MyISAM DEFAULT CHARSET=utf8
またMENTAの方にもセットアップを行ないます。
menta.cgi
menta.cgiに、mysqlの設定を記述します。
# あなたのアプリの設定 application => { title => '単純なBBS', mysql => { domain => 'localhost', dns => 'DBI:mysql:simple_bbs', user => 'root', password => '', }, },
plugins/sql.pl
標準で付いてくるプラグインsql.plを利用したいと思います。
デフォルトでは、SQLiteを使う設定になっているので書き換えます。
sql_dbhの部分を下記のように書き換えました。
sub sql_dbh_for_mysql { if (@_) { my @args = @_; if ($MENTA::STASH->{sql_dbh}) { $MENTA::STASH->{sql_dbh}->disconnect; undef $MENTA::STASH->{sql_dbh}; } my $dbh = DBI->connect(@args) or die "DBに接続できません: $DBI::errstr"; $dbh->{unicode} = 1; $MENTA::STASH->{sql_dbh} = $dbh; $dbh; } else { $MENTA::STASH->{sql_dbh} ||= do { my $dsn = config->{application}->{sql}->{dsn} or die "設定に application.sql.dsn がありません"; my $dbh = DBI->connect($dsn) or die "DBに接続できません: $DBI::errstr"; $dbh->{unicode} = 1; $dbh; }; } } sub sql_dbh { my $conf = MENTA::config->{application}->{mysql}; sql_dbh_for_mysql($conf->{dns},$conf->{user},$conf->{password}); }
ページの作成
app/controllerにページ表示用のプログラムを記述していきます。
書き込み一覧ページ (http://localhost:5555/)
書き込みフォームと書き込まれた内容を表示するページを作成します。
プログラムファイル名とテンプレート名は、それぞれ「index.pl」「index.mt」にします。
# index.pl use MENTA::Controller; sub run { my ( $rows, $pager ) = sql_select_paginate( 'SELECT id, title, message, datetime FROM bbs ORDER BY id DESC', [], { page => param('page') || 1, rows => 10, } ); for my $r (@$rows) { utf8::decode($r->{title}); utf8::decode($r->{message}); } render_and_print('index.mt', $rows, $pager); }
? my ($rows, $pager, $test) = @_; <html> <head> <meta http-equiv="Content-Type" content="text/html;charset=UTF-8"> <title>単純な掲示板</title> </head> <body> <h1>単純な掲示板</h1> <form method="POST" action="<?= uri_for('create') ?>"> <div> Title <input type="text" name="title"> </div> <div>Message</div> <div> <textarea name="message" cols="50" rows="10"></textarea> </div> <div> <input type="submit" value="Post"> </div> </form> <div> ? foreach my $r (@$rows) { <div> <hr> <div>タイトル: <?= $r->{title} ?> (<?= $r->{datetime} ?>)</div> <div>メッセージ</div> <div><?= $r->{message} ?></div> </div> ? } </div> </body> </html>
書き込み処理プログラム (http://localhost:5555/create)
データベースに書き込み内容を格納する処理を記述します。
フォームの「Post」ボタンを押すと起動します。
入力チェック、文字数チェックを行なって、不適切ならエラーメッセージを出すようにしています。
# create.pl use MENTA::Controller; use DateTime; sub run { my $title = param('title'); my $message = param('message'); return render_and_print('error.mt','Please input title') unless $title; return render_and_print('error.mt', 'Please input message') unless $message; return render_and_print('error.mt', 'Title is too long') if length $title > 30; return render_and_print('error.mt', 'Message is too long') if length $message > 100; my $dt = DateTime->now( time_zone => 'Asia/Tokyo' ); my $datetime = $dt->strftime('%Y/%m/%d %H:%M:%S'); sql_prepare_exec('INSERT INTO bbs (title, message, datetime) VALUES (?,?,?)', $title, $message, $datetime); redirect('/'); }
? my ($message) = @_; <html> <head> <meta http-equiv="Content-Type" content="text/html;charset=UTF-8"> <title>Error</title> </head> <body> <?= $message ?> </body> </html>
起こった問題
いくつか問題があったので、メモしておきます。
データベースから取ってきた日本語文字が化ける
テンプレートに挿入される際にUTF8の文字が化けます。
プログラムに直書きしているときは、「use utf8;」をコントローラに記述すれば直ります。
しかし、データベースから取ってきたものに対しては、他の処理が必要です。
今回は、下記のように処理をすることによって、文字化けを回避しました。
for my $r (@$rows) { utf8::decode($r->{title}); utf8::decode($r->{message}); }
UTF8のフラグが問題みたいです。こちらの詳細は後日調べたいと思います。
undefinedな変数の値を表示しようとするとエラーが出る
テンプレートにundefinedな変数の値を表示する事は禁止されているみたいです。
エラーが出ます。
こちらは動作としては、エラーが出ずに、空白が出力されてほしいところです。
HTML::Templateでは、オプション設定することによってできたはずです。
どうような設定ができる予感。
参考文献
- 作者: 木本裕紀,B5変形
- 出版社/メーカー: 技術評論社
- 発売日: 2009/07/25
- メディア: 大型本
- 購入: 2人 クリック: 33回
- この商品を含むブログ (4件) を見る
この本の第5章にある「ひとことメッセージ掲示板」を基に作りました。
この本の筆者のBlogではMojolicious::Liteで書き直されています。