Laravel3でやりがちなミス
現行のLarave 3.2でやりがちなミスを紹介しましょう。
どうしてもルートが通らない
次のようなコードで悩みました。
Route::get('my-root', array('as' => 'route-name'), function() { return view('view-name'); });
ルートに名前をつけようとして、カッコの閉じる場所を間違えてしまっています。もともとRoute::getは2つしか引数を取りません。IDEを使用している場合、当然指摘してもらえると考えがちですが、NetBeansでもEclipsでも指摘されません。もしかしたら、PhpStromなら教えてくれるかも知れません。(確かめていません。)
実行しても、内容が空のレスポンスヘッダーだけが送られます。ページは真っ白になります。
間違いに気付いたのは、最後の閉じかっこが}));
になるはずなのに、});
だったからです。
もちろん正しくは、次のように書きます。
Route::get('my-root', array('as' => 'route-name', function() { return view('view-name'); }));
ベテランさんほど、気が付きにくいかも知れませんね。慣れると思い込んじゃいますから。
フォームがエラーになる
きちんとフォームも作ったし、ルートも絶対正しい。なのに、500になる。絶対にLaravelがおかしいと思ったら、多分CSRFフィルターをそのルートに対して設定しているのに、フォームにSCRFトークンを入れ忘れています。
標準のCSRFフィルターはroutes.php
に書かれています。フォームに埋め込まれたトークンがなかったり、改変されている場合、500エラーになるようにコーディングされています。CSRFで引っかかると、500エラーになるという感覚にどうも馴染めないため、気が付かず、ルーティングの間違いと思い違いをして悩みます。
何でもエラーになる
同じくCSRF絡みです。POSTだけでなくGETにもCSRFフィルターを指定し、フォームが出力されず悩みます。
具体的には次のコードで悩むんです。
Route::any('post/(:num)', array('before' => 'csrf', ...
any()はHTTP変数、つまりリクエストのメソッドによらずこのルートを登録するものです。当然GETの場合にも'csrf'フィルターが通されます。GETのリクエストにはCSRFトークンはありません。CSRFトークンはフォームに埋め込まれているものですからね。そのため、フォームを表示することすら出来ず、CSRFフィルターに引っかかり続けます。前記の通りデフォルトなら500、内部エラー発生のレスポンスでエラーページが表示されます。
勢いがつきすぎて…
調子よくコーディングしており、ルーティングを書き始める。最初にgetルートを書き、お次はフォームの内容の処理だと、putルートを書く。そしてフォームが処理されず悩むことになります。
当然、フォームの処理だから、デフォルトならpostです。でも、コーディングに勢いがある時だとgetと同じ3文字のputをさくっと書いちゃう。すると、なんだか気持ちが良すぎて、本当はpostだと気が付かなくなるんです。
マイグレーションがエラーになる
php artisan migrate
がどうしてもエラーになる。php artisan migrate:install
は通っているんです。きっとデータベース関連の間違いだろうと、設定ファイルを見直すが、いくら探しても間違いがありません。
するとある瞬間、そう言えば開発環境用にlocalフォルダー作ったことを思い出すわけです。そこでlocalフォルダー下の設定ファイルを見直しますが、間違いはやはりありません。
思いっきり悩んで、突然コマンドラインツールはURLから環境を判断しているわけでないと思い出します。ブラウザ経由でアクセスするときはドメイン名が付いているので、それで開発環境か実働環境か、その他のものか判断つきますが、コマンドラインの環境は環境変数か、もしくは--env=local
とオプションで指定しなくてはなりません。
それをややこしくしているのが、php artisan migrate:install
コマンドです。設定が正しかろうと、間違っていようと、実際に仕事した時も、しない時も、同じメッセージを出します。間違っている時に、正しいようなメッセージを出すのはクリティカル。開発者は正しいものと思い込んでしまうがため、気が付きづらく、発見まで時間がかかります。
使用していないクッキーがエラーになる
初心者でまず面食らうのが、ある時から使用していないはずのクッキーがエラーになることです。
クッキーの最大サイズは約4Kバイトです。これを超えて書き込もうとしているとPHPのエラーになります。これが起きるのです。
原因はセッションのドライバーがデフォルトではcookie
になっていることです。セッションの保持に使用されるデバイスをドライバーで指定するのですが、これがクッキーになっているため、セッションに保存される情報は当然全部クッキーに書き込まれます。そのため、オーバーフローを起こします。
では、Laravelは4Kバイト以上の情報をいつもセッションに保存するのでしょうか?
答えはセッションに保存する内容によります。英語で書かれたチュートリアルを行なっていると、よくこのエラーに合います。英語の環境でチュートリアルを行なってもエラーにならないのでしょう。
Laravelや他のフレームワークでも、次のページに表示するメッセージをセッションに保存する仕組みになっているものがあります。英語の場合、そのまま保存しますから、4Kバイト内に収まります。(通常、暗号化はされます。)日本語の場合、内部でUTF8で扱われているにせよ、保存時にそのままではなく、エンコードされ、更に暗号化で保存バイト数が文字数の何倍にも膨れ上がります。ですから、日本語を含めUTF-8のメッセージを使用したりすると、これが起きてしまいがちです。
とはいえ、日本人向けのシステムでは、日本語を使用するので、英語のメッセージばかりというわけに行きません。問題はクッキーの保存領域の小ささです。セッションの保存先を変更すればよいだけです。
保存先には、ファイルやデータベースなども選べます。お手軽なのはファイルです。ドライバーにfile
を指定し、保存先のstorage/sessions
が「その他ユーザー」から書き込み可能になっていることを確認してください。
データベースを選ぶ場合、ドライバーにdatabase
を指定します。そして、セッションテーブルを生成する必要があります。Artisanコマンドラインツールで生成できます。
php artisan session:table
リターンのつけ忘れ
これも何度かはまります。まず、最初はビューやリダイレクトにreturn文を付け忘れ、なんでページに何も表示されないのか悩みます。
もうちょっとLaravelに慣れてきて、ORMのEloquentを使い出すと、リレーションの定義でreturn文を忘れ、どうしても関係が取得出来なくて悩みます。
両方共エラーを出してくれるといいんですけどね。多分、Laravel4では、多少改善されるでしょう。