Permalink
Switch branches/tags
Nothing to show
Find file Copy path
Fetching contributors…
Cannot retrieve contributors at this time
534 lines (428 sloc) 19.2 KB

Perl入学式

第6回 Webアプリ編


諸注意

  • 会場について
    • 飲食・喫煙・トイレetc
  • 写真撮影について
    • 写真撮影NGな方はお手数ですが申し出てください

紹介

  • 講師・サポーター紹介

本日の内容

Mojolicious を使って Web アプリケーションを作ろう!

  • Mojolicious の準備
  • HTTP の基礎
  • Mojolicious 入門
  • 簡易 BBS の作成

皆さんで自己紹介


Mojolicious の準備


Mojolicious のインストール

$ cpanm -n Mojolicious
  • エラーになる場合は以下のコマンドを試してみてください。
$ curl -L https://cpanmin.us | perl - -n Mojolicious
  • https://がエラーになる場合はhttp://でも問題ありません。

Mojolicious とは?

  • Perl の Web アプリケーションフレームワーク(WAF)です。
  • MVCフレームワークの、Modelを除いた(ViewとControllerの)機能を持っています。
  • Perl 5.10.1 以降で動作します。

Mojoliciousの資料


HTTP の基礎


HTTPとは?

  • HyperText Transfer Protocolのことです。
  • Web ブラウザと Web サーバの間でコンテンツの送受信を行うための通信手順(プロトコル)です。

HTTP のメソッド

よく使うのは以下の2つです。

GET

  • (主に)サーバからデータを取得する

POST

  • (主に)サーバにデータを送信する

Mojolicious の ひな形


最初に

  • この入門では、難しい表現を避けるために、厳密には正しくない事も書いてあります。
  • この入門に書いていない沢山の引数やコマンドについては、本家サイトなどのリファレンスをご覧ください。

ひな形を作る

$ mojo generate lite_app hello.pl
  • Mojoliciousをインストールすると、mojoというコマンドが使えるようになります。
  • mojo generate lite_appと入力すると、Mojolicious::Liteを使ったひな形を作成してくれます。
  • hello.plは作成するファイル名です。
  • 現在のディレクトリにhello.plというファイルが作成されているか確認して下さい。

起動してみる

$ morbo hello.pl
  • Mojoliciousをインストールすると、morboというコマンドも使えるようになります。
  • morboは開発用のアプリケーションサーバーを起動してくれます。
  • 画面上にServer available at http://127.0.0.1:3000.と表示されれば起動しています。
  • Web ブラウザで http://127.0.0.1:3000 にアクセスしてみましょう。

コード解説(Line 1 - 2)

#!/usr/bin/env perl
use Mojolicious::Lite;
  • Mojolicious::LiteMojolicious を簡単に使うためのモジュールです。
  • use Mojolicious::Lite; とすることで、自動的にstrictwarningsutf8Perl 5.10 featureが有効になります。

コード解説(Line 1 - 2)

use strict;
use warnings;
use utf8;
use feature ':5.10';
  • つまり、use Mojolicious::Lite;を書くだけで、ついでに上記のように書いているのと同じということです。

コード解説(Line 4 - 5)

# Documentation browser under "/perldoc"
plugin 'PODRenderer';
  • Mojoliciousでは、機能を拡張するプラグインが利用できます。
  • ここでは、Mojolicious::Plugin::PODRendererを使用しています。
  • http://127.0.0.1:3000/perldocにアクセスするとMojoliciousのPODを読むことができます。
  • [参考資料]

コード解説(Line 7 - 10)

get '/' => sub {
  my $c = shift;
  $c->render(template => 'index');
};
  • ウェブアプリケーションでは、URLごとに処理を変更できると便利です。
  • このようなURLごとに処理を振り分ける機能のことをrouterdispatcherと呼びます。
  • Mojolicious::Liteでは、HTTPのGETリクエスト用のrouterとしてgetという関数が用意されています。

コード解説(Line 7 - 10)

get '/' => sub { ... };
  • 見慣れない書き方ですが、これは、getという関数に、2つの引数を渡しているだけです。
  • 一つ目の引数が'/'という文字列、二つ目の引数がコードリファレンスです。
  • このように書くことで、HTTPのGETメソッドで/にアクセスした時の処理をsub { ... }に書くことができます。

コード解説(Line 7 - 10)

my $c = shift;
$c->render(template => 'index');
  • コードリファレンスの最初の行は、フレームワークのコントローラーを受け取っています。
  • コントローラーにはrenderというメソッドがあり、どのような出力をするのかを書くことができます。
  • ここではindexのテンプレートを使用して出力するように書いています。

コード解説(Line 12)

app->start;
  • Mojolicious::Liteを使う場合は、コードの最後にこの命令文を書かなければいけません。

  • 当面は「お約束」として覚えておけばよいでしょう。


コード解説(Line 13)

__DATA__
  • __DATA__以降は文字通りデータとして使えます。Mojolicious::Liteでは、ここにテンプレートなどを書いておくことができます。

コード解説(Line 15)

@@ index.html.ep
  • Mojolicious::Liteでは、@@ index.html.epと書いておくと、次に@@が出てくるまでの範囲をindex.html.epというファイルとして扱うことができます。このようにすれば、多くのファイルを必要とせずにプログラムを書くことができます。
  • epは、Mojoliciousの標準的なテンプレート機能を使用するための拡張子です。拡張子をepにすることで、テンプレートであることを示します。

コード解説(Line 16 - 18)

% layout 'default';
% title 'Welcome';
Welcome to the Mojolicious real-time web framework!
  • %は、その行をPerlのコードとして実行したい時に書きます。ここでは出てきませんがHTMLタグのように<% Perlのコード... %>と書くこともできます。
  • Mojoliciousの標準的なテンプレートでは、このように書くとテンプレートの中でPerlのコードが実行できます。
  • なお、%では、その行全体がPerlのコードとして扱われますが、<% ... %>の場合は、...の部分のみがPerlのコードとして扱われます。

コード解説(Line 16 - 18)

  • layoutはレイアウトを指定します。ここではdefaultを指定しています。(後ほど詳しく説明します)
  • titleはタイトルを指定します。ここではWelcomeを指定しています。(後ほど詳しく説明します)
  • それ以外の通常の文字列は、そのままHTMLとして表示されます。

コード解説(Line 20)

@@ layouts/default.html.ep
  • @@が書いてあるので、これ以降はlayouts/default.html.epとして扱われます。この文字列はパス扱いなので、layoutsディレクトリにあるdefault.html.epというファイルを示します。
  • Mojolicious::Liteでは、layoutsディレクトリ内にレイアウト用のテンプレートを用意でき、layoutコマンドで切り替えて使うことができます。
  • 先のコードで% layout 'default';と指定しましたので、layoutsディレクトリにあるdefault.html.epをレイアウトとして使用することになります。

コード解説(Line 21 - 25)

<!DOCTYPE html>
<html>
  <head><title><%= title %></title></head>
  <body><%= content %></body>
</html>
  • <%= ... %>(あるいは%=から始まる行)は、Perlのコードを実行するだけでなく、値を表示したい時に書きます。
  • <%= title %>は、先のコードで% title 'Welcome';と指定したので、Welcomeと表示されます。
  • titleは、テンプレート内で使える関数で、このようにHTMLファイルのタイトルを取得したり設定したりできる、便利な関数です。
  • contentは、レイアウトテンプレート内で使える関数で、通常のテンプレートの中身を取得する関数です。

Mojolicious 入門


変数を渡す

get '/' => sub {
  my $self = shift;
  $self->stash(title => 'Hello');
  $self->render('index');
};
% title 'Welcome'; # => 削除する
  • $self->stash で, テンプレート内の変数に変数を渡せる

練習問題

@@ profile.html.ep
<html>
<head><title><%= $name %>のプロフィール</title></head>
<body style='padding: 30px;'>
  私の名前は<%= $name %>です.<br>
  趣味は<%= $hobby %>で, 好きなプログラミング言語は<%= $language %>です.
</body>
</html>
  • このようなテンプレートを用意し, stash で name, hobby, language 変数に値を代入し, 自己紹介ページを作成しよう
    • render で profile テンプレートを指定しましょう

テンプレートの中の特殊記号

% if ($num1 == 1 ) { # %
%= 'hoge';    # %=
    <% if ($num2 == 1 ) { %> # <% ... %>
        <%= $hoge %>         # <%= ... %>
    <% } %>
% }
  • %のように, テンプレートの中で特別な意味を持つ記号がある

テンプレートの中の特殊記号

% if ($num1 == 1 ) { # %
    ...
% }
  • %が先頭にある行は, その後ろのPerlのコードを実行する

テンプレートの中の特殊記号

%= 'hoge';    # %=
  • %=が先頭にある行は, その後ろのPerlのコードを実行して, その結果をテンプレート内に直接埋め込む
    • 返り値を出力するので, print 'hoge';と書いてしまうと1になる!
    • printの実行結果は1なので...

テンプレートの中の特殊記号

<% if ($num2 == 1 ) { %> # <% ... %>
    <%= $hoge %>         # <%= ... %>
<% } %>
  • <% ... %>, <%= ... %>は, それぞれ%, %=をHTMLタグやテキストの中で使えるようにしたもの

練習問題

  • fizzbuzzテンプレートを用意して, 1から100までのfizzbuzzを表示してみましょう
    • 但し, fizzbuzzの処理は全てfizzbuzzテンプレートの中に書くようにしましょう
  • fizzbuzz
    • 3で割り切れる場合「Fizz」
    • 5で割り切れる場合「Buzz」
    • 3でも5でも割り切れる場合「fizzbuzz」
    • いずれも満たさない場合「その数をそのまま」

簡易 BBS の作成


雛形を作る

$ mojo generate lite_app BBS

PODRenderer

# Documentation browser under "/perldoc" # 削除
plugin 'PODRenderer'; # 削除
  • PODRenderer は Mojolicious のプラグインで, perldoc を見れるようにするもの
  • 削除する前に、localhost:3000/perldoc にアクセスしてみよう!

FORM 作成

Welcome to the Mojolicious real-time web framework! # 削除
  • index テンプレートにある, もともとの文字列を削除する

FORM 作成

%= form_for '/' => begin
  %= text_field 'body'
  %= submit_button '投稿する'
% end
  • 削除したところに, フォームを出力するコードを書く
    • form_for, text_field, submit_buttonなどは, Mojolicious のhelperという機能で定義されたPerlの関数(サブルーチン)

FORM 作成

  • ここまで出来たら, 保存してから, ブラウザをリロード (あるいはhttp://localhost:3000にアクセス) してみましょう
  • フォームから投稿しても画面上は何も変わりません
    • 次に, フォームから投稿された文字列を画面に表示するようにしてみよう

GET

  %= submit_button '投稿する'
% end
<p><%= $entry %></p>
  • まずは index テンプレートを上記のように変更する
  • <%= $entry %> は, テンプレート内の変数

GET

get '/' => sub {
  my $self = shift;
  my $entry = $self->param('body'); # 追加
  $self->render('index');
};
  • form の情報を取得するために, 上記のように 1 行追加する
  • $self->param('body') は フォームから投稿した body という名前の値を取得する

GET

get '/' => sub {
  my $self = shift;
  my $entry = $self->param('body');
  $self->stash(entry => $entry); # 追加
  $self->render('index');
};
  • 取得した情報をテンプレートに渡すため, $self->stash(entry => $entry) を挿入する
  • entry に変数 $entry を渡したので, テンプレートで $entry が使用可能になる

GET

  • ここまで出来たら, 保存してからブラウザをリロード (あるいはhttp://localhost:3000にアクセス) してみよう
  • フォームに文字を入力して, 「投稿する」ボタンをクリックしてみよう!

POST

  • 先ほどのフォームは, HTTP でいうところのGETメソッドを利用してデータを送信していました
  • GET でのリクエストは文字数の制限(おおよそ 2KB 程度)があるので、掲示板のような多くのデータを送信する必要がある場合は適当ではありません
    • このような場合, POST によるリクエストを行うとよいです

POST

@@ post.html.ep # 新しいテンプレートを用意する
% layout 'default';
% title '出力'; # タイトルを変更
%= form_for '/post' => method => 'POST' => begin # 投稿先などを変更
  %= text_field 'body'
  %= submit_button '投稿する'
% end
<p><%= $entry %></p>
  • index.html.ep の部分をコピーして, post.html.ep というテンプレートを作成する
  • form_for に書いた method => 'POST' で, get ではなく post で送信するようになる

POST

@@ index.html.ep
% layout 'default';
% title '入力フォーム'; # タイトルを変更
%= form_for '/post' => method => 'POST' => begin # 投稿先などを変更
  %= text_field 'body'
  %= submit_button '投稿する'
% end
  • @@ index.html.ep では, $entry を表示させないようにする
  • その他, メソッドやタイトルも変更しておこう

POST

get '/' => sub {
  my $self = shift;
  $self->render('index');
};

post '/post' => sub {
  my $self = shift;
  my $entry = $self->param('body');
  $self->stash(entry => $entry);
  $self->render('post');
};
  • perl コードも変更しよう
    • 細々とした違いに注意!

POST

  • ここまで出来たら, 保存してから, ブラウザをリロード (あるいはhttp://localhost:3000にアクセス) してみよう
  • フォームに長い文字を入力して, 「投稿する」ボタンをクリックしてみよう!

記事を蓄える

  • 記事を蓄えるための方法としては, いくつかの方法がある
    • DB (データベース) を利用
    • 外部ファイルに書き込み保存
  • 今回は時間の制約上, データを蓄える方法として, 配列を用いる
    • 言うまでもなく, 配列は Web アプリケーションが停止した時点で全てのデータが消えるので, 現実的ではない!
    • MySQLSQLiteなどのデータベースを使うのがオススメです

記事を蓄える

@@ index.html.ep
% layout 'default';
% title '入力フォーム';
%= form_for '/post' => method => 'POST' => begin
  %= text_field 'body'
  %= submit_button '投稿する'
% end
% for my $entry (@{$entries}) {
    <p><%= $entry %></p>
% }
  • テンプレートに, 投稿済みの記事( $entries に格納されている )を表示するよう変更を加える

記事を蓄える

my @entries = (); # 空の配列を宣言
get '/' => sub {
  my $self = shift;
  $self->stash(entries => \@entries); # 配列のリファレンスをテンプレートに渡す
  $self->render('index');
};

post '/post' => sub {
  my $self = shift;
  my $entry = $self->param('body');
  push @entries, $entry; # 配列に格納
  $self->stash(entry => $entry);
  $self->render('post');
};

記事を蓄える

  • ここまで出来たら, 保存してから, ブラウザをリロード (あるいはhttp://localhost:3000にアクセス) してみよう
  • 文字の投稿をいくつか繰り返した後に, http://localhost:3000にアクセスしてみよう!

リダイレクト

  • 別のページへ遷移(移動)するための機能
    • 今回の場合, /postで記事を投稿した後に記事を表示するページである/に戻るようにする
  • Mojolicious ビルトインの redirect_to を使用すればよい

redirect_to

post '/post' => sub {
  my $self = shift;
  my $entry = $self->param('body');
  push @entries, $entry;
  $self->stash(entry => $entry);
  $self->redirect_to('/'); # 追加
};
  • redirect_to を利用して, /へのページ遷移を追加する
    • postのテンプレートはもう必要ないので, 削除しても問題ない

最終問題

  • これまで作成してきた簡易 BBS を, 改造してみましょう!
  • 例えば...?
    • 名前/メールアドレスを入力/表示できるようにする...
    • メールアドレスが「age」であれば, 記事をpushではなくunshiftする...
    • テンプレートを整理して, 見た目を綺麗にする...
      • Twitter Bootstrapを使ってみる...

まとめ

  • 非常に簡単ではありますが, BBS (のような) Web サービスを開発してみました
    • 時間の制約上, 紹介できなかった部分 (適切な記事の蓄え方など...) は紹介できませんでしたが, Perl を使った Web サービスの開発の基本的な流れは, このようになっています
    • 今日ここまで紹介してきた内容は, 基礎中の基礎です. 「 Web サービスを作ろう!」となると, やはりまだまだ挑戦しなければならない「壁」はいくつもあります
  • その時困ったら, Perl入学式の資料や, スタッフを是非頼って下さい!

質問タイム


お疲れさまでした