@nqounetです。
連載「URL短縮サポーターを作ってみよう」の第5回です。
前回の振り返り
第4回では、Digest::SHAを使ってURLから短縮コードを生成する方法を学びました。

前回学んだ内容を簡単に振り返ります。
use Digest::SHA qw(sha1_hex);でSHA-1ハッシュ関数を使えるようにしたsubstr(sha1_hex($url), 0, 6)で先頭6文字の短縮コードを生成した- Perlのハッシュ変数
%urlsにURLとコードの対応を保存した(仮実装)
今回は、サーバーを再起動してもデータが消えないよう、データベースを導入します。
今回のゴール
第5回では、以下を達成することを目標とします。
- データの永続化が必要な理由を理解する
- DBIモジュールの役割を知る
- SQLiteデータベースに接続する方法を学ぶ
サーバー再起動したら消えちゃう!
タカシさんの問題
前回、短縮コードの生成が動くようになり、タカシさんは喜んでいました。しかし翌日、タカシさんから連絡がありました。
「昨日登録したURLが全部消えてる!」
これは前回触れた「現状の制限」が原因です。Perlのハッシュ変数%urlsはメモリ上にしか存在しないため、サーバーを停止すると内容はすべて失われてしまいます。
永続化の必要性
Webアプリケーションでデータを保持し続けるには、永続化(persistence)が必要です。永続化とは、プログラムが終了してもデータが残るようにすることです。
永続化の方法はいくつかあります。
- ファイルに書き出す
- データベースに保存する
- 外部ストレージサービスを利用する
今回は、データベースを使った永続化を選択します。データベースを使えば、データの検索や管理が簡単になり、将来的な機能拡張にも対応しやすくなります。
なぜSQLiteなのか
データベースにもMySQL、PostgreSQL、SQLiteなど様々な種類があります。今回はSQLiteを採用します。理由は以下のとおりです。
- サーバーの設定が不要(ファイル1つで動作する)
- インストールが簡単
- 小規模なアプリケーションには十分な性能
SQLiteはデータベースの内容を単一のファイルに保存します。そのため、設定ファイルやサーバープロセスを別途用意する必要がありません。個人用のURL短縮サービスには最適な選択です。
DBIでデータベースに接続しよう
DBIとは
PerlでデータベースにアクセスするにはDBIモジュールを使います。DBIはDatabase Interfaceの略で、様々なデータベースに統一されたインターフェースでアクセスできるモジュールです。
DBIを使うと、MySQLでもPostgreSQLでもSQLiteでも、ほぼ同じコードでデータベースを操作できます。データベースの種類ごとの違いは、DBD(Database Driver)モジュールが吸収してくれます。
今回はSQLiteを使うので、DBIに加えてDBD::SQLiteモジュールも必要です。
モジュールをインストールする
DBIとDBD::SQLiteをインストールします。ターミナルで以下のコマンドを実行してください。
| |
データベースに接続する
DBIを使ってSQLiteデータベースに接続するコードを見てみましょう。
| |
このコードがデータベース接続の基本形です。各部分を詳しく解説します。
use DBI;
| |
DBIモジュールを読み込みます。これでデータベース操作に必要な関数やメソッドが使えるようになります。
DBI->connect()
| |
DBI->connect()はデータベースへの接続を確立し、データベースハンドル($dbh)を返します。引数は4つあります。
第1引数(データソース名)
"dbi:SQLite:dbname=urls.db"
この文字列はDSN(Data Source Name)と呼ばれ、3つの部分で構成されています。
dbi: DBIを使うことを示す固定のプレフィックスSQLite: 使用するデータベースドライバ(DBD::SQLiteを使用)dbname=urls.db: データベースファイルのパス
このコードを実行すると、カレントディレクトリにurls.dbというファイルが作成されます。このファイルがSQLiteデータベースの実体です。
第2引数・第3引数(ユーザー名・パスワード)
| |
SQLiteはファイルベースのデータベースなので、ユーザー認証の仕組みがありません。そのため、ユーザー名とパスワードは空文字列を指定します。
MySQL等のサーバー型データベースを使う場合は、ここに適切な認証情報を設定します。
第4引数(オプション)
| |
接続オプションをハッシュリファレンスで指定します。
RaiseError => 1: エラー発生時に例外を投げる。これを設定しておくと、エラーを見逃さずに済むAutoCommit => 1: 各SQL文を自動的にコミットする。トランザクションを手動で管理しない場合はこの設定が便利
接続を確認して切断する
接続が成功したかを確認し、使い終わったら切断するコードを見てみましょう。
| |
コードの各部分を解説します。
接続の確認
| |
DBI->connect()が成功すると、データベースハンドル($dbh)が返されます。このハンドルは真の値なので、if ($dbh)で接続成功を確認できます。
$dbh->{sqlite_version}はDBD::SQLite固有の属性で、使用しているSQLiteのバージョンを取得できます。接続が正しく行われているかの確認に便利です。
エラー処理
| |
接続に失敗した場合、$DBI::errstrにエラーメッセージが格納されています。今回はRaiseError => 1を設定しているため、実際にはエラー時に自動的に例外が投げられますが、明示的なエラー処理も書いておくと安心です。
切断
| |
データベースとの接続を明示的に切断します。Perlのスクリプトが終了すると自動的に切断されますが、明示的に切断する習慣をつけておくと良いでしょう。
動作確認
スクリプトを実行する
上記のコードをconnect_and_disconnect.plとして保存し、ターミナルで実行してください。
| |
以下のような出力が表示されれば成功です。
| |
バージョン番号は環境によって異なります。
データベースファイルの確認
スクリプトを実行後、カレントディレクトリにurls.dbというファイルが作成されていることを確認してください。
| |
このファイルがSQLiteデータベースの実体です。サーバーを再起動しても、このファイルが残っている限りデータは失われません。これで永続化の第一歩が完了しました。
まとめ
今回学んだこと
第5回では、以下のことを学びました。
- メモリ上のデータはサーバー再起動で消えるため、永続化が必要である
- PerlでデータベースにアクセスするにはDBIモジュールを使う
DBI->connect("dbi:SQLite:dbname=urls.db", "", "", { RaiseError => 1, AutoCommit => 1 })でSQLiteに接続できる$dbh->disconnectで接続を切断する
次回予告
次回は「データの住所を決めよう — テーブル設計」をテーマに、URLを保存するためのテーブル構造を設計します。CREATE TABLE文を使って、id、original_url、short_code、created_atといったカラムを定義していきます。お楽しみに。