Subscribed unsubscribe Subscribe Subscribe

例があまり良くないというか、何をやりたいアプリなのかそもそもよく分からないし、書き方も微妙なところがちょくちょくあったので、さくっと書きなおしてみた。

#!/usr/bin/env perl
use Mojolicious::Lite;  # Mojo::Lite を use すると自動で use strict; と use warnings; をしてくれる
use DBI;
use utf8;

my $dsn = "dbi:mysql:dbname=recipe";                                                                             
my $dbh = DBI->connect(
    $dsn,
    "YOUR MySQL USERNAME",
    "YOUR MySQL PASSWORD",
    {   
        RaiseError => 1,
        AutoCommit => 1,
    },  
);

get '/' => sub {
    my $self = shift;

    # dbからデータを引く
    my @urls = @{
        $dbh->selectall_arrayref('select * from recipe_url', {Slice => {}})
    };  

    $self->render(urls => \@urls);

} => 'index';

post '/add' => sub {
    my $self = shift;
    
    my $url = $self->param('recipe_url');

    # dbにデータを挿入する
    $dbh->do("insert into recipe_url (url) values (\'$url\')");
    # ダブルクォートの中でシングルクォートを書くときは、
    # 念のためにシングルクォートの前に\を入れる

    return $self->redirect_to('/');
};

post '/delete' => sub {
    my $self = shift;
    my $target_id = $self->param('id');

    # dbからデータを削除する
    $dbh->do("delete from recipe_url where id = \'$target_id\'");
    
    return $self ->redirect_to('/');
};

app->start();

__DATA__

@@ index.html.ep
<html>
  <head>
    <title>My Favorite Recipes</title>
  </head>                                                                                                      
  <body>
  <h1>My Favorite Recipes</h1>
    <form method="post" action="/add">
      <input type="text" name="recipe_url" placeholder="http://cookpad.com/recipe/XXXXXXXX"/>
      <input type="submit" value="add">
    </form>
    <form method="post" name="delete" action="/delete">
      <% for my $data (@$urls) { %>
        <input type="hidden" name="id" value="<%= $data->{id} %>"/>
        <a href="<%= $data->{url} %>" target="_blank">
        <%= $data->{url} %></a><input type="submit" value="delete"/><br/>
      <% } %>
    </form>
  </body>
</html>
<style type="text/css">
  input[type="text"] {
    width: 250px;
  }
</style>

下準備

MySQLにデータベースを作る
# mysqlコンソールに入る
mysql -uroot -p

# データベースを作る
mysql> create database recipe charset utf8;

# データベースを選択
mysql> use recipe;

# mysqlにテーブルを作る
mysql > \
create table recipe_url (                     \
  id int(10) unsigned not null auto_increment, \
  url varchar(1024) not null,                  \
  primary key (`id`)                           \
) engine=innodb default charset=utf8;
  • Q: テーブルって何?
  • A: http://rfs.jp/sb/sql/s01/01-19.html (全部読む必要なし。テーブル、フィールド、レコード、プライマリキーなどの概念がつかめればOK)

コードの解説

Perlを使ってMySQLからデータを参照/更新する方法

基本的には

  • 複数のレコードを参照する場合には selectall_arrayref
  • 単一のレコードを参照する場合には selectrow_hashref
  • レコードを挿入(insert) / 更新(update) / 削除(delete) する場合には do

と覚えておけばOK。prepare とか fetchrow_array とか execute とかは冗長なので忘れましょう。

selectrall_arrayref

複数のレコードを参照する場合に使う。

# 第二引数の {Slice => {}} はおまじないのようなものだと思いましょう
my $rows = $dbh->selectall_arrayref("select * from recipe", {Slice => {}});

#=> $rows には複数レコードが格納された配列(リファレンス)が返る。配列として使いたい場合はデリファレンスしてやる
# $rows = [
#     {id => 1, url => "http://..."},
#     {id => 2, url => "http://..."},
#     ...
# ];

selectrow_hashref

単一のレコードを参照する場合に使う。

my $row = $dbh->selectrow_hashref("select * from recipe where id = 1", {Slice => {}});
# $row = {id => 1, url => "http://..."};

Q: そもそもselect文てなんぞ?
A: http://rfs.jp/sb/sql/s03/03-15.html, http://rfs.jp/sb/sql/s03/03_2-2.html

do

insert, update, delete などの「データを新しく作る」「既存のデータを変更する」SQL文を発行する場合に使う。

$dbh->do("insert into recipe (url) values (\'$url\')");
$dbh->do("update from recipe set url = $url where id = $id");
$dbh->do("delete from recipe where id = $id");

redirectとは?

あるページに「飛ばす」こと。(例えばログインせずにはてなのページにアクセスしたらログインページに飛ばされるのも、リダイレクトを使っている)
上で使っているコードで言うと

$self->redirect_to('/');

は / のページに飛ばしている。

ほか、分からなければ

ガンガン聞いてください!