Perl
の環境を構築しておきましょう。Mojolicious
をインストールしておきましょう。$ cpanm Mojolicious
$ mojo generate lite_app
[chmod] myapp.pl 744
myapp.pl
というファイル名プログラムが作成されているので、そのプログラムを実行します。$ morbo myapp.pl
Server available at http://127.0.0.1:3000.
http://localhost:3000
にアクセスしてみてください。Welcome to the Mojolicious real-time web framework!
#!/usr/bin/env perl
use utf8; # <この行を挿入
use Mojolicious::Lite;
use utf8;
した状態のPerlは、日本語などのマルチバイト文字でも、文字として正しく扱うことができます。# use utf8;していない状態
$ perl -e 'print length "abcあいう";'
# use utf8;した状態
$ perl -Mutf8 -e 'print length "abcあいう";'
# Documentation browser under "/perldoc" # <この行を削除
plugin 'PODRenderer'; # <この行を削除
PODRenderer
はMojolicious
のプラグインで、perldoc
を綺麗に見るためのプラグインです。http://localhost:3000/perldoc
にアクセスして確認してみてください。Welcome to the Mojolicious real-time web framework! # <削除
%= form_for '/' => begin
%= text_field 'body'
%= submit_button '投稿する'
% end
form_for
、text_field
、submit_button
などは、Mojolicious
のhelper
という機能で定義されたPerlの関数(サブルーチン)です。helper
については、次回詳しく説明する予定です。
参考になるページ
http://localhost:3000
にアクセス)してみてください。 %= submit_button '投稿する'
% end
<p><%= $body %></p> <この行を挿入
<%= $body %>
は、テンプレートの中でPerlの変数などを表示するときに使用します。$body
という変数の値を表示する、という意味になります。index.html.ep
)の最後には.ep
という拡張子がついています。Embedded Perl
の頭文字をとったものです。Mojolicious
が標準で使えるテンプレートのシステムを示しています。Mojolicious
のテンプレートでPerlのコードを実行させる書き方としては、タグ
と行
の二種類があります。# タグ
<% Perlのコード %>
<%= Perlのコード %>
<%== Perlのコード %>
# 行
% Perlのコード
%= Perlのコード
%== Perlのコード
get '/' => sub {
my $self = shift;
my $body = $self->param('body'); # < この行を追加
$self->param('body')
は、フォームから投稿したbody
という名前がついている値を取得します。 my $body = $self->param('body');
$self->stash(body => $body); # < この行を追加
$self->stash()
に、値を渡すと、テンプレートでも使えるようになります。body
に、変数$body
を渡したので、テンプレートでは$body
として使えるようになります。http://localhost:3000
にアクセス)してみてください。投稿する
ボタンをクリックしてみてください。http://www.yahoo.co.jp/
を開いて、ページの情報をコピー&貼り付けして投稿してみましょう。HTTP
でいうところのGET
でのリクエストです。GET
でのリクエストは文字数の制限(おおよそ2KB程度)がありますので、掲示板など、多くのデータを送信する必要がある場合は適しません。POST
によるリクエストを行います。HTTP
については、ネットワークの知識も必須となるので、Perl入学式では深く取り上げません。GET
とPOST
であり、それらをうまく使い分けられれば当分は問題ありません。index.html.ep
の部分をすべてコピーして貼り付けて、post.html.ep
というテンプレートを作成します。http://localhost:3000/post
にアクセスした時に読み込まれます。# @@ index.html.epを貼り付け
@@ post.html.ep # テンプレート名を変更
% layout 'default';
% title '出力'; # タイトルを変更
%= form_for '/post' => method => 'POST' => begin # 投稿先などを変更
%= text_field 'body'
%= submit_button '投稿する'
% end
<p><%= $body %></p>
form_for
に書いたmethod => 'POST'
で、get
ではなくpost
で送信するようになります。@@ index.html.ep
の方は、$body
を表示しないようにしておきます。form_for
も忘れずに変更しておきましょう。title
も変更しておきましょう。@@ index.html.ep
% layout 'default';
% title '入力フォーム'; # タイトルを変更
%= form_for '/post' => method => 'POST' => begin # 投稿先などを変更
%= text_field 'body'
%= submit_button '投稿する'
% end
get
の部分のコードをすべてコピーして貼り付けます。body
の処理をしている部分を削除します。get '/' => sub {
my $self = shift;
my $body = $self->param('body'); # 貼り付けしたあと削除
$self->stash(body => $body); # 貼り付けしたあと削除
$self->render('index');
};
body
の処理が書いてある方を一部変更します。post '/post' => sub { # この行を変更
my $self = shift;
my $body = $self->param('body');
$self->stash(body => $body);
$self->render('post'); # この行を変更
};
param
は、get
でもpost
でも同じように動作します。http://localhost:3000
にアクセス)してみてください。投稿する
ボタンをクリックしてみてください。post
のテンプレートは、index.html.ep
をコピー&貼り付けして作成しましたが、フォームの部分を両方共変更する必要がありました。Mojolicious
には、テンプレートを共通化する仕組みがあります。%= form_for '/post' => method => 'POST' => begin
%= text_field 'body'
%= submit_button '投稿する'
% end
form.html.ep
として定義します。@@ form.html.ep
%= form_for '/post' => method => 'POST' => begin
%= text_field 'body'
%= submit_button '投稿する'
% end
form.heml.ep
を使うにはinclude
という命令を使います。index
の部分は以下のようになります。@@ index.html.ep
% layout 'default';
% title '入力フォーム';
%= include 'form';
post
の部分は以下のようになります。@@ post.html.ep
% layout 'default';
% title '出力';
%= include 'form';
<p><%= $body %></p>
http://localhost:3000
にアクセス)してみてください。include
を使うことで、共通の部品として利用できます。post
の部分を変更します。my $body = $self->param('body'); # この行の後ろに追加
my $datafile = qq{myapp.dat};
open my $fh, '>>', $datafile or die $!;
print $fh qq{$body\n};
close $fh;
open
の行は、$datafile
を追加モード(>>
)で開いています。die
)させます。例外を発生させる、とも言います。$!
にはエラーの内容が入っています。$fh
で操作します。$fh
のような変数を、ファイルハンドル、と言います。print
のあとにファイルハンドルを書き、その次に出力する文字列を書きます。qq{}
は、"(ダブルクォーテーション)
と同じ意味です。出力する文字列の中に"
があるような場合に使うとエスケープが不要になるので、コードが読みやすくなります。
参考になるページ
close
をした時点でファイルの取り扱いを終えたことが、コードを読む人にもわかります。将来の自分自身のために、ちゃんと閉じておきましょう。
参考になるページ
http://localhost:3000
にアクセス)してみてください。morbo myapp.pl
したターミナルを確認し、以下のようなエラーが出ているのを確認してください。Wide character in print at myapp.pl line 15.
use utf8;
した状態のPerlは、日本語も含め文字をちゃんと扱うように考えられています。Mojolicious
が最終的に出力する文字列に関しては、Mojolicious
自体が適切に処理しています。Encode
というモジュールを使います。use Mojolicious::Lite;
use Encode; # < この行を追加
jcode.pl
やJcode.pm
を知っているかもしれませんが、それらのことは、もう忘れてください。モダンなPerlを理解する上での弊害になります。UTF-8
にして、use utf8;
を書いておくことが推奨されています。use Encode;
すると、幾つかの関数が使えるようになります。(エクスポートされる、とも言います)encode_utf8
を使ってエンコードした文字列をファイルに書き込むようにします。print $fh qq{$body\n}; # < この行を以下のように変更
↓
print $fh encode_utf8(qq{$body\n});
http://localhost:3000
にアクセス)してみてください。@@ index.html.ep
)に、どのように表示するかを考えながら書いて行きましょう。% for my $entry (@{$entries}) {
<p><%= $entry %></p>
% }
get '/' => sub {
my $self = shift; # この行の後ろに追加します。
my $datafile = qq{myapp.dat};
open my $fh, '<', $datafile or die $!;
my @entries = <$fh>;
close $fh;
<$fh>
のように<
と>
でくくります。chomp
を使います。 @entries = map { decode_utf8($_) } @entries;
$self->stash(entries => \@entries);
get '/' => sub {
my $self = shift;
my $datafile = qq{myapp.dat};
open my $fh, '<', $datafile or die $!;
my @entries = <$fh>;
close $fh;
@entries = map {decode_utf8($_)} @entries;
$self->stash(entries => \@entries);
$self->render('index');
};
http://localhost:3000
にアクセス)してみてください。myapp.pl
は、以下のようになります。#!/usr/bin/env perl
use utf8;
use Mojolicious::Lite;
use Encode;
get '/' => sub {
my $self = shift;
my $datafile = qq{myapp.dat};
open my $fh, '<', $datafile or die $!;
my @entries = <$fh>;
close $fh;
@entries = map {decode_utf8($_)} @entries;
$self->stash(entries => \@entries);
$self->render('index');
};
post '/post' => sub {
my $self = shift;
my $body = $self->param('body');
my $datafile = qq{myapp.dat};
open my $fh, '>>', $datafile or die $!;
print $fh encode_utf8(qq{$body\n});
close $fh;
$self->stash(body => $body);
$self->render('post');
};
app->start;
__DATA__
@@ form.html.ep
%= form_for '/post' => method => 'POST' => begin
%= text_field 'body'
%= submit_button '投稿する'
% end
@@ index.html.ep
% layout 'default';
% title '入力フォーム';
%= include 'form';
% for my $entry (@{$entries}) {
<p><%= $entry %></p>
% }
@@ post.html.ep
% layout 'default';
% title '出力';
%= include 'form';
<p><%= $body %></p>
@@ layouts/default.html.ep
<!DOCTYPE html>
<html>
<head><title><%= title %></title></head>
<body><%= content %></body>
</html>