PHPマイクロフレームワークSlimを使ってTinyURLを作ってみた
Slim は Ruby の Sinatra の様なマイクロフレームワークで、PHP で簡単な Webアプリを書くにはちょうどいいと思う。今回はその Slim を使って、短縮 URL(bitly みたいなやつ)を作ってみた。なお、tokuhirom さんの Amon2 のサンプルからアイデアを拝借しています。
See also
インストール
Slim のインストールは Composer で行う。Ruby の Bundler や Perl の Carton の様なライブラリ管理ツールである。
% cd /path/to/project % curl -s https://getcomposer.org/installer | php
composer.json に以下を記述する。
{ "require": { "slim/slim": "2.*" } }
以下のコマンドでインストールする。vendor ディレクトリに slim が格納される。
% php composer.phar install
ディレクトリレイアウト
ベターなディレクトリレイアウトがあるかもしれないけど、手探り状態で作ったので、良いディレクトリレイアウトがあったら教えて下さい!
project/ composer.json composer.lock composer.phar root/ # ドキュメントルート .htaccess # PHP ビルトインサーバを使用したので今回は必要なし index.php tmpl/ # テンプレート index.php result.php vendor/ slim/slim/ # Slimライブラリ sql/ sqlite3.sql development.db
TinyURL を作る
まずは DB のテーブルを作成する。以下のスキーマを作成して、sql/sqlite3.sql で保存する。
create table tinyurl ( key varchar(20) primary key, url text );
以下のコマンドを実行して、DB のテーブルを作成する。
% sqlite3 development.db < sql/sqlite3.sql
これで DB の準備は完了。
今回はあくまで動くものを作ることが目的なので、エラーチェックやバリデーション等は甘いです。
root/index.php
<?php require '../vendor/autoload.php'; $app = new \Slim\Slim(array( "debug" => true, "templates.path" => "../tmpl" )); $db = new PDO('sqlite:../development.db'); // 引数で指定した長さのランダムな文字列を生成 function stringRandom($len = 5) { if (!is_numeric($len) || $len <= 0) { die("positive interger is required."); } $str = ''; for ($i = 0; $i < $len; ) { $num = mt_rand(0x30, 0x7A); if ((0x30 <= $num && $num <= 0x39) || (0x41 <= $num && $num <= 0x5A) || (0x61 <= $num && $num <= 0x7A)) { $str .= chr($num); $i++; } } return $str; } $app->get('/', function () use ($app) { $app->render("index.php"); }); $app->post('/create/', function () use ($app, $db) { $req = $app->request(); $url = $req->post("url"); if (!$url) { $app->redirect('/'); return; } // dup check $sth = $db->prepare('SELECT key FROM tinyurl WHERE url = ? LIMIT 1;'); $sth->execute(array($url)); $result = $sth->fetch(PDO::FETCH_ASSOC); $key = $result['key']; if (!$key) { // create new one $key = stringRandom(6); $sth = $db->prepare('INSERT INTO tinyurl (key, url) VALUES (?, ?);'); $sth->execute(array($key, $url)); } $app->render('result.php', array("tinyurl" => $req->getUrl() . '/g/' . $key)); }); $app->get('/g/:key', function ($key) use ($app, $db) { if (!$key) { $app->redirect('/'); return; } $sth = $db->prepare('SELECT url FROM tinyurl WHERE key = ? LIMIT 1;'); $sth->execute(array($key)); $result = $sth->fetch(PDO::FETCH_ASSOC); $url = $result['url']; $app->redirect(($url) ? $url : '/'); }); $app->run(); ?>
tmpl/index.php
<!DOCTYPE html> <html> <head> <title>TinyURL</title> <meta charset="UTF-8"> </head> <body> <h1>tinyurl</h1> <form action="/create/" method="POST"> <input type="text" name="url" value=""> <input type="submit" name="submit" value="tiny!"> </form> </body> </html>
tmpl/result.php
<!DOCTYPE html> <html> <head> <title>TinyURL</title> <meta charset="UTF-8"> </head> <body> <h1>tinyurl</h1> <div><?php echo htmlspecialchars($tinyurl, ENT_QUOTES, "UTF-8"); ?></div> <a href="/">return to top</a> </body> </html>