Laravel3でやりがちなミス

タグ: PHP   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では、多少改善されるでしょう。