Laravel4でView Composerの設定をする場所
View Composerの設定をする場所の私案。特にデフォルトの場所が決まってるわけではないので好きな場所で設定すればいいんだけど、かといってroutes,.phpに書くのもダサいので、収まりのいい場所を模索。
ServiceProviderで
app/Atijust/ViewComposerProvider.php
<?php namespace Atijust; use Illuminate\Support\ServiceProvider; use View; class ViewComposerProvider extends ServiceProvider { public function register() { /* NOP */ } public function boot() { View::composer('sidebar', 'Atijust\SidebarViewComposer'); } }
app/composers.phpで
app/composers.php
<?php View::composer('sidebar', 'Atijust\SidebarViewComposer');
app/start/global.php
<?php require app_path().'/composers.php';
app/composers.phpを作成しView Composerを定義。 app/start/global.phpでrequireする。
なんとなくapp/composers.phpのほうが収まりがいい気がする。app/routes.phpでコントローラ、app/composers.phpでコンポーザーみたいな。ただ、数が多くなった場合は、ServiceProviderで整理したほうがいいかもしれない(おそらくこれはルートにも言える)。
Laravel4でブログチュートリアルっぽいのをやってみた - その2
Laravel4でブログチュートリアルっぽいのをやってみた - その1では、記事の一覧と表示を実装した。今回は記事の投稿を実装する。編集、削除については実装しないことにした。編集と投稿はほとんど同じだし、削除はコードが短く特に面白いところもないので。
リファクタリング
機能を実装していく前に、テストしやすいように予めリファクタリングしておくことにする。
app/controllers/PostController.php
<?php class PostController extends BaseController { public function index() { $posts = Post::all(); return View::make('post.index', ['posts' => $posts]); } public function show($id) { $post = Post::findOrFail($id); return View::make('post.show', ['post' => $post]); } }
前回作成したPostControllerではPostモデルのstaticメソッドを呼び出しておりテストがやりにくい。
Postモデルをモックできるようにコンストラクタで注入するようにする。
app/controllers/PostController.php
<?php class PostController extends BaseController { protected $post; public function __construct(Post $post) { $this->post = $post; } public function index() { $posts = $this->post->all(); return View::make('post.index', ['posts' => $posts]); } public function show($id) { $post = $this->post->findOrFail($id); return View::make('post.show', ['post' => $post]); } }
コンストラクタに渡されたPostモデルをプロパティに保存しておき、アクションではそれを使うようにした。このようにしておけば、コンストラクタにダミーのインスタンスを渡すことにより、スムーズにテストを行うことができる。
アプリケーションの実行時は、LaravelのIoCコンテナによりPostモデルが渡される。IoCコンテナはリフレクションでコンストラクタのタイプヒントを調べて、対応するクラスのインスタンスを自動的に注入してくれる。なので、Postモデルを注入するコードを自前で書く必要はない。
バリデーション
記事の投稿ではユーザから入力されたデータをバリデーションする必要がある。アクションを実装するまえにバリデーションを用意しておくことにする。
バリデーションをどこに実装するべきかについては諸説あるようだが、今回はモデルにバリデーション機能を持たせる(楽だから)。
app/models/Post.php
<?php class Post extends Eloquent { protected $fillable = ['title', 'body']; protected $errors; public function validate(array $params) { $validator = Validator::make($params, [ 'title' => 'required', 'body' => 'required', ]); if ($validator->passes()) { return true; } else { $this->errors = $validator->messages(); return false; } } public function errors() { return $this->errors; } }
Laravelのバリデーション機能はValidator
から利用できる。titleとbodyを必須に指定している。失敗した場合はエラーメッセージをプロパティに保存しておき、モデルのerrors()
メソッドで取得できるようにしておく。
ここでは自前で実装しているが、Eloquentを拡張してモデルにバリデーション機能をつけてくれるパッケージなんかもあるので、そういうのを使うのもいいかもしれない。
記事の投稿
記事を投稿するフォームを表示するgetCreate
アクションと、実際に記事をDBに保存するpostCreate
アクションの2つを作成する。
app/controllers/PostController.php
<?php public function getCreate() { return View::make('post.create'); } public function postCreate() { $attrs = Input::only(['title', 'body']); if (!$this->post->validate($attrs)) { return Redirect::action('PostController@getCreate') ->withErrors($this->post->errors()) ->withInput(); } $this->post->create($attrs); return Redirect::action('PostController@index'); }
HTTPリクエストに付随する各種情報にはInputからアクセスできる。Inputにはかゆいところに手が届く便利メソッドが色々と用意されており、ここでは指定した名前のパラメータだけを取り出せるonly()
を使っている。
バリデーションが失敗したら投稿フォームにリダイレクトする。投稿フォームにエラーメッセージと前回の入力値を表示するために、withErrors()
とwithInput()
でエラーメッセージと入力値をセッションに保存している。
記事の保存にはPostモデルのcreate()
を使っている。引数に渡した配列からエンティティを作成しDBにINSERTしてくれる。create()
でセットできるのはモデルの$fillable
に指定したものだけなので注意。create()
に限らず配列で一気にエンティティに値をセットする系のメソッドは$fillable
で明示的に許可されたプロパティ以外には使えない。もし許可されてないプロパティに値をセットしようとすると例外が発生する。
投稿フォームのViewを作成する。
app/views/post/create.blade.php
<!doctype html> <html lang="ja"> <head> <title>Demo Blog</title> <meta charset="UTF-8"> </head> <body> <h1>記事投稿</h1> @foreach ($errors->all() as $error) <p>{{{ $error }}}</p> @endforeach <form action="{{ action('PostController@postCreate') }}" method="post"> {{ Form::token() }} <input type="text" name="title" value="{{{ Input::old('title') }}}" placeholder="タイトル"><br> <textarea name="body" rows="3">{{{ Input::old('body') }}}</textarea><br> <input type="submit" value="投稿"> </form> </body> </html>
アクションのリダイレクト処理においてwithErrors()
でセッションに保存したエラーメッセージはViewでは$errors
で参照できる。
withInput()
で保存した前回のユーザ入力はInput::old()
で取得できる。
{{ Form::token() }}
でフォームの隠しパラメータにCSRF対策のためのトークンをセットしている。このトークンは後述のルートフィルタでチェックする。
最後にルーティングを定義する。
app/routes.php
<?php Route::get('/create', 'PostController@getCreate'); Route::post('/create', ['before' => 'csrf', 'uses' => 'PostController@postCreate']);
POSTの/create
にcsrf
ルートフィルタを設定している。csrf
はLaravelに元から用意されているフィルタで、トークンをチェックしてくれる。
以上で記事の投稿機能は完成。組み込みサーバを立ち上げ、http://localhost:8000/create
にアクセスすれば、投稿フォームが表示される。
最後に
取り敢えず、機能としてはこれで完成。Laravelにも多少馴れてきたような気がする。 テストについてはエントリをあらためて書きたいと思う。
Laravel4でブログチュートリアルっぽいのをやってみた - その1
手を動かして覚えたいので、ちょうどいい課題としてCakePHPのブログチャートリアルっぽいのをLaravel4でやってみた。
動作要件
Lravel4の動作要件は以下の2つ。
- PHP5.3.7以上
- MCrypt拡張
手元ではPHP5.5.5と組み込みサーバで動作を確認している。
インストール
Composerを使ってインストール。
$ composer create-project laravel/laravel --prefer-dist demo-blog Installing laravel/laravel (v4.0.9) - Installing laravel/laravel (v4.0.9) Loading from cache Created project in demo-blog Loading composer repositories with package information Installing dependencies (including require-dev) ### 中略 ### Writing lock file Generating autoload files Generating optimized class loader Application key [nROO9YVu3ZmwxXMlRDI32sz1l0mxo71n] set successfully.
zipをダウンロードしてきてインストールすることもできるみたいだけど、どのみちComposerが必要なのであまり意味はない。
動作確認
インストールが成功したかどうか確認。
プロジェクトのトップディレクトリで./artisan serve
を実行する。
$ cd demo-blog $ ./artisan serve Laravel development server started on http://localhost:8000
PHPの組み込みサーバが立ち上がるので、ブラウザでhttp://localhost:8000
にアクセスする。Laravelのロゴが表示されれば成功。
artisanはLaravelのコマンドラインツールで、開発に便利な各種機能を提供している。ここでは単にPHPの組み込みサーバを立ち上げるのに使ったが、DBのマイグレーションやシーディングなど、なにかとお世話になるコマンド。
Laravelの設定
タイムゾーン
app/config/app.php
'timezone' => 'Asia/Tokyo',
デフォだとUTCなので変更しておく。
データベース
app/config/database.php
'mysql' => array( 'driver' => 'mysql', 'host' => 'localhost', 'database' => 'demo_blog', 'username' => 'root', 'password' => '', 'charset' => 'utf8', 'collation' => 'utf8_unicode_ci', 'prefix' => '', ),
ブログ用にdemo_blog
というデータベースを使うことにする。
MySQL以外にもPostgres、SQLite、SQL Serverがサポートされているので、どれを使うかは好みで。設定方法は設定ファイルのコメントに書いてある。
データベースの作成
Laravelのマイグレーション機能を使ってテーブルを作成する。
demo_blog
データベースはコマンドラインなりツールであらかじめ作成しておく。
まずはartisanでマイグレーションのひな形を作成する。
$ ./artisan migrate:make create_posts_table --table=posts --create Created Migration: 2013_10_30_002418_create_posts_table Generating optimized class loader
スキーマビルダーを使ってテーブルを組み立てる。
app/database/migrations/2013_10_30_002418_create_posts_table.php
<?php use Illuminate\Database\Schema\Blueprint; use Illuminate\Database\Migrations\Migration; class CreatePostsTable extends Migration { /** * Run the migrations. * * @return void */ public function up() { Schema::create('posts', function(Blueprint $table) { $table->increments('id'); $table->string('title', 50); $table->text('body'); $table->dateTime('updated_at'); $table->dateTime('created_at'); }); } /** * Reverse the migrations. * * @return void */ public function down() { Schema::drop('posts'); } }
updated_at
とcreated_at
というカラムがあれば、ORMがモデルの更新、作成時に自動的に時刻を設定してくれる。
マイグレーションを実行。
$ ./artisan migrate Migration table created successfully. Migrated: 2013_10_30_002418_create_posts_table
これでdemo_blog
データベースにposts
テーブルが作成された。
Postモデルの作成
LaravelにはEloquentというORMが含まれている。オーソドックスなActiveRecordタイプで使いやすい。
モデルのクラスファイルはオートローダでロードできるならどこに置いてもいいけど、取り敢えず最初から用意されているapp/models
ディレクトリを使うことにする。
app/models/Post.php
<?php class Post extends Eloquent { }
モデルは規約によってクラス名の複数形のテーブルと対応する。もちろん規約外のテーブル名を使うことも出来る。
ダミーデータの用意
データベースにブログ記事のダミーデータを用意する。 コマンドライン、あるいは適当なツールでデータベースに直接データを入れてもいいのだが、Laravelに用意されているSeed機能を使ってみることにする。
app/database/seeds/DatabaseSeeder.php
にデフォルトのSeederクラスが用意されているのでこれを使う。
app/database/seeds/DatabaseSeeder.php
<?php class DatabaseSeeder extends Seeder { /** * Run the database seeds. * * @return void */ public function run() { Eloquent::unguard(); DB::table('posts')->truncate(); Post::create(['title' => 'はじめてのLaravel', 'body' => 'Hello, Laravel!']); } }
Postモデルを使ってレコードを作成。
artisanで実行する。
$ ./artisan db:seed Database seeded!
Postコントローラの作成
コントローラはapp/controllers
に設置する。例によってオートローダでロードできるならここ以外のディレクトリに設置することもできる。
app/controllers/PostController.php
<?php class PostController extends BaseController { public function index() { $posts = Post::all(); return View::make('post.index', ['posts' => $posts]); } public function show($id) { $post = Post::findOrFail($id); return View::make('post.show', ['post' => $post]); } }
記事一覧を表示するindex
アクションと、記事を表示するshow
アクションを用意した。先ほど作成したPostモデルからブログ記事を取得し、View::make()
でビューをレンダリングしている。
次にアクションとURLを結びつけるためにルーティングを設定する。ルーティングの設定はapp/routes.php
に記述する。もちろんこれ以外の場所(ServiceProviderとか)で設定することもできる。
app/routes.php
<?php Route::get('/', 'PostController@index'); Route::get('/{id}', 'PostController@show');
Postビューの作成
LaravelにはBladeというシンプルなテンプレートエンジンが含まれている。今回はこれを使うことにする。 もちろんだけど、Blade以外にPHP、Twig、Smartyなどなんでも好きなものを使うことができる。Packagistで検索するとLaravel用のパッケージが見つかる。
まずはPostController@indexに対応する記事一覧のビューファイル。
app/views/post/index.blade.php
<!doctype html> <html lang="ja"> <head> <title>Demo Blog</title> <meta charset="UTF-8"> </head> <body> <h1>Demo Blog</h1> @foreach ($posts as $post) <a href="{{ action('PostController@show', $post->id) }}">{{{ $post->title }}}</a> {{ $post->created_at }}<br /> @endforeach </body> </html>
制御構文は@
からはじまる。
{{
と}}
で囲まれた部分はecho
される。{{{
と}}}
で囲まれている場合はエスケープされてからecho
される。
URLの生成には各種ヘルパーメソッドが用意されている。ここではコントローラのアクションに引数を指定してURLを生成している。
次はPostController@indexに対応する記事を表示するビュー。
app/views/post/show.blade.php
<!doctype html> <html lang="ja"> <head> <title>Demo Blog</title> <meta charset="UTF-8"> </head> <body> <h1>{{{ $post->title }}}</h1> <p>{{{ $post->body }}}</p> </body> </html>
以上でブログの記事一覧と記事表示の機能は完成。
コマンドラインからartisanでPHPの組み込みサーバを立ち上げ、http://localhost:8000
にアクセスすれば記事一覧が表示されるはず。
記事の投稿、編集、削除とユニットテスト
ちょっと疲れたので、記事の投稿、編集、削除については後日あらためて作成することにする。いまどきテストを書かないわけにもいかないので、テストもしっかり用意したいと思う。
最後になったが、Laravelの学習には日本語ドキュメントを使わせていただいた。翻訳して公開してくださった川瀬氏に感謝。
SSH代替のmoshでMac OSX10.8(Mountain Lion)からEC2インスタンスに接続
WiMAX経由でEC2インスタンスにSSH接続して作業していると、時間帯によってはシェルの反応がもっさりだったり、接続が切れちゃったりでストレスマッハでハゲる。
そこで、回線品質が低い場合でも快適に作業できると噂のmoshを導入。
まずはMBA。インストーラがあるみたいだけど、素直に(?)brewでインストールする。
$ brew install mobile-shell
なるほど。moshはMobile Shellの略なわけね。
次はEC2。OSはAmazon Linux。パッケージないみたいなのでソースからビルドする(あとで気づいたんだけどEPELにあった。試してないけど。)。./configure
したらProtocol Bufferが必要だといわれたので、あらかじめ入れておく。Purotocol Buffer以外にも依存しているモジュールがあるようだが、すでに導入済みだったみたい。お試しなので、インストール先は/opt
に。
$ wget http://mosh.mit.edu/mosh-1.2.4.tar.gz $ tar xvf mosh-1.2.4.tar.gz $ cd mosh-1.2.4 $ sudo yum install protobuf-devel $ ./configure --prefix=/opt/mosh $ make $ sudo make install
通信にUDPポート60000-61000を使うので、Security Groupを操作して開けておく。
以上で準備は完了。moshはサーバ側であってもデーモンを常駐させておく必要がないので、upstartのスクリプトを書いたりしなくてもよい。
クライアント側のMacからアクセスしてみる。
$ mosh --ssh="ssh -i aws.pem" --server="/opt/mosh/bin/mosh-server" ec2-user@hogehoge.compute.amazonaws.com
ログイン自体はSSH経由で行うようだ。ログインに使うSSHのキーを指定したい場合は--sshオプションを使う。サーバ側は非標準な場所にインストールしたので、mosh-serverコマンドのパスを指定する必要がある。
繋がった。レスポンスが心持ち良くなったかも?
moshは低品質回線での使い勝手を良くする以外にも、Ctrl-Cの挙動を改善してくれたりするので(でっかいファイルをcatしてしまってCtrl-Cが効かなくなったことありません?)、メインのPCでもSSHの代わりにいいかもしれない。
PHPのHTTPクライアントライブラリ「Guzzle」を使ってみる(その2)
その1のつづき。
Guzzleには、Service Descriptionといって、インターフェースをJSON(PHP配列でも可)で定義しておけば、コードを一行も書くことなくWebサービスにアクセスできる機能がある。
JSONでAPIのインターフェースを定義して
{ "operations": { "getProfile": { "httpMethod": "GET", "uri": "/api/restful/v1/people/{+guid}/{+selector}{?fields,format}", "parameters": { "guid": { "location": "uri" }, "selector": { "location": "uri" }, "fields": { "location": "query" }, "format": { "location": "query", "default": "json" } } } } }
こんなふうに使う。
<?php require_once 'vendor/autoload.php'; use Guzzle\Plugin\Oauth\OauthPlugin; use Guzzle\Service\Client; use Guzzle\Service\Description\ServiceDescription; $client = new Client('http://sb.sp.app.mbga.jp/'); $client->addSubscriber(new OauthPlugin(array( 'consumer_key' => 'xxxxxxxxxxxxxxxxxxxx', 'consumer_secret' => 'xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx', ))); $client->setDescription(ServiceDescription::factory(__DIR__.'/people.json')); $result = $client->getCommand('getProfile', array( 'guid' => '123456', 'selector' => '@self', 'fields' => 'id,nickname', ))->execute(); var_dump($result);
結果は配列以外にも定義次第でいろんな形式で返せる。
array(4) { 'startIndex' => int(1) 'person' => array(2) { 'nickname' => string(7) "hoge" 'id' => string(17) "sb.mbga.jp:123456" } 'itemsPerPage' => int(1) 'totalResults' => int(1) }
動作確認のサンプルなので、ここでは基本的なことしかやってないけど、ドキュメントを読む限りService Descriptionはかなり柔軟で強力な機能のよう。AWS SDK for PHPの実装にも使われていたりするので、実用的なWebサービスクライントの作成も十二分に可能だろう。
PHPのHTTPクライアントライブラリ「Guzzle」を使ってみる(その1)
Mobageのドキュメントがデベロッパー以外にも公開されたみたいですね。これでブログに気兼ねなくMobageネタが書けます。というわけで、さっそく。
GuzzleというHTTPクライアントライブラリが良さげなので、MobageのAPIにアクセスしてみました。OAuthプラグインもあって超お手軽。そして、お手軽でありながら、高機能。パラレルリクエストもできるっぽい。
取り敢えずPeopleAPIを叩いてみる。
<?php require_once 'vendor/autoload.php'; use Guzzle\Http\Client; $client = new Client('http://sb.sp.app.mbga.jp/'); $client->addSubscriber(new Guzzle\Plugin\Oauth\OauthPlugin(array( 'consumer_key' => 'xxxxxxxxxxxxxxxxxxxx', 'consumer_secret' => 'xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx', ))); echo $client->get(array('/api/restful/v1/people{/guid}{/selector}{?fields,format}', array( 'guid' => '123456', 'selector' => '@self', 'fields' => 'id,nickname,thumbnailUrl', 'format' => 'json', )))->send()->getBody();
これで実行すると、、、
Fatal error: Uncaught exception 'Guzzle\Http\Exception\ClientErrorResponseException' with message ' in /Users/atijust/Develop/mbga_api/vendor/guzzle/guzzle/src/Guzzle/Http/Exception/BadResponseException.php on line 48 Guzzle\Http\Exception\ClientErrorResponseException: Client error response [status code] 401 [reason phrase] Unauthorized [url] http://sb.sp.app.mbga.jp/api/restful/v1/people/123456/%40self?fields=id%2Cnickname%2CthumbnailUrl&format=json (略)
ファッ!?
URLテンプレートで置き換えてる部分の@
がパーセントエスケープされとる。。。
URI template RFCによると、Path Segment Expansion: {/var}では予約文字はパーセントエスケープされるそう。
えー、、、
Reserved Expansion: {+var}を使えば予約文字のパーセントエスケープを回避できるっぽいので、取り敢えずそれでやってみる。
<?php echo $client->get(array('/api/restful/v1/people/{+guid}/{+selector}{?fields,format}', array( 'guid' => '123456', 'selector' => '@self', 'fields' => 'id,nickname,thumbnailUrl', 'format' => 'json', )))->send()->getBody();
今度はうまくいった。
{ "startIndex" : 1, "person" : { "nickname" : "hoge", "thumbnailUrl" : "http://sb-sp.mbga.jp/img_u/123456/0.1.gif", "id" : "sb.mbga.jp:123456" }, "itemsPerPage" : 1, "totalResults" : 1 }
(もにょるなぁ)
その2へつづく。
HerokuにNginx+PHP5.4+MySQLな環境を構築する
HerokuといえばRubyのためのPaaSという印象が強いのですが、ひっそりとPHPも使えます。しかし、PHPのバージョンが5.3.10と少し古いのが難点。そこで、サードパーティのbuildpackを使ってPHP5.4環境を構築してみました。buildpackというのは環境構築スクリプトのパッケージで、サードパーティのbuildpackを使えば、公式にサポートされていない環境も簡単にセットアップして使うことができます。サードパーティのものには、CやらCommon LispやらErlangやらなんでもありです。
今回はHeroku上に最新のPHP5.4 + Nginx環境を30秒で構築するで紹介されているiphoting / heroku-buildpack-php-tylerを使いたいと思います。
特徴としては
- Nginx+PHP-FPM
- PHP5.4(apc, memcache, memcached, mysql, pgsql, phpredis, mcrypt, newrelic, sqlite)
- Composerによる依存性管理
Nginx+PHP-FPMな構成で、Apacheがわからない(っていうか、Nginxでいいじゃん的な)ゆとりエンジニアの自分にも設定いじれそうなのがいいですね。Composerで環境構築時に自動的にパッケージをインストールしてくるのも有難い。phpinfoはこんな感じ。
セットアップ
取り敢えず、動作確認用のindex.phpを作成しgitのリポジトリを作成します。
$ mkdir heroku-test $ cd heroku-test $ vi index.php <?php echo 'Hello, Heroku!'; $ git init $ git add . $ git commit -m '最初の登録'
Herokuコマンドにbuildpackを指定してアプリを作成します。
$ heroku create -s cedar -b git://github.com/iphoting/heroku-buildpack-php-tyler.git Creating radiant-badlands-4098... done, stack is cedar BUILDPACK_URL=git://github.com/iphoting/heroku-buildpack-php-tyler.git http://radiant-badlands-4098.herokuapp.com/ | git@heroku.com:radiant-badlands-4098.git Git remote heroku added
あとはpushするだけ。環境構築に数十秒かかります。
$ git push heroku master Counting objects: 3, done. Writing objects: 100% (3/3), 261 bytes, done. Total 3 (delta 0), reused 0 (delta 0) -----> Fetching custom git buildpack... done -----> PHP app detected -----> Fetching Manifest https://s3.amazonaws.com/heroku-buildpack-php-tyler/manifest.md5sum -----> Installing Nginx Bundling Nginx v1.2.7 https://s3.amazonaws.com/heroku-buildpack-php-tyler/nginx-1.2.7-heroku.tar.gz -----> Installing libmcrypt Bundling libmcrypt v2.5.8 https://s3.amazonaws.com/heroku-buildpack-php-tyler/libmcrypt-2.5.8.tar.gz -----> Installing libmemcached Bundling libmemcached v1.0.7 https://s3.amazonaws.com/heroku-buildpack-php-tyler/libmemcached-1.0.7.tar.gz -----> Installing PHP Bundling PHP v5.4.11 https://s3.amazonaws.com/heroku-buildpack-php-tyler/php-5.4.11-with-fpm-heroku.tar.gz -----> Installing newrelic Bundling newrelic daemon v2.9.5.78 https://s3.amazonaws.com/heroku-buildpack-php-tyler/newrelic-2.9.5.78-heroku.tar.gz -----> Copying config files -----> Installing boot script -----> Done with compile -----> Discovering process types Procfile declares types -> (none) Default types for PHP -> web -----> Compiled slug size: 35.8MB -----> Launching... done, v5 http://radiant-badlands-4098.herokuapp.com deployed to Heroku To git@heroku.com:radiant-badlands-4098.git * [new branch] master -> master
もうこれで動きます。簡単すぎ!
$ heroku open
アドオンでMySQLを使えるようにする
HerokuといえばPostgreSQLですが、サードパーティのMySQLアドオンがいくつかあるようです。
MySQLでアドオンを検索したところこの3つが出てきました。特に決め手はないのですが、取り敢えずClear DB MySQL Databaseを使ってみたいと思います。無料のigniteプランを使用します。
インストールはこれだけ。
$ heroku addons:add cleardb:ignite Adding cleardb:ignite on radiant-badlands-4098... done, v8 (free) Use `heroku addons:docs cleardb:ignite` to view documentation.
heroku config
で接続情報が見れます。
$ heroku config | grep CLEARDB_DATABASE_URL CLEARDB_DATABASE_URL => mysql://adffdadf2341:adf4234@us-cdbr-east.cleardb.com/heroku_db?reconnect=true ※接続情報は公式ドキュメントのサンプルより
mysqlコマンドで接続可能。
$ mysql --host=us-cdbr-east.cleardb.com --user=adffdadf2341 --password=adf4234 heroku_db
PHPからつなぐ場合は、環境変数から接続情報を取得してパースします。公式ドキュメントのUsing ClearDB with PHPを参照。接続情報をハードコーディングすることも出来るのですが、ソース公開するとき困るので、環境変数使う感じで。
$cleardb = parse_url(getenv('CLEARDB_DATABASE_URL'));
$conn = new PDO(
sprintf("mysql:dbname=%s;host=%s", substr($cleardb['path'], 1), $cleardb['host']),
$cleardb['user'],
$cleardb['pass']
);
以上、HerokuでNginx+PHP5.4+MySQLな環境を構築してみました。いくつかコマンドを実行するだけでサクサクと環境が構築できてしまうのはスゴイです。VPSを借りて自分で管理するのも面白いのですが、ちょっとしたものを公開するときにお手軽な選択肢があるのはいいですね。
次はSymfony2でも入れてみようかな。Treasure Dataのアドオンも面白そう。