『Laravelリファレンス』を読んだ/Laravel雑感

入手自体はかなり早かったんですが、サンプルコードを試す機会を逸していてレビューが遅れました。。。

Laravelとは

Laravelは、2016年現在、最も人気のあるPHPフレームワークといってよいと思います。個人的には、Laravelの特徴は以下の3点だと思ってます。

(1) 高機能なフルスタックフレームワーク

PHPには、「フルスタック」を標榜するフレームワークがいくつもありますが、その中でもLaravelは高機能な部類に入ります。Symfonyという、それ自体高機能なフレームワークのコンポーネントを、さらに拡張するような作りになっています。私は現在は主にSymfonyを使用していますが、「この機能Symfonyにもほしい!」というものが結構あります。

(2) 変化の速さ

Laravelは変化の速いフレームワークです。メジャーバージョンの遷移は以下のようになっていて、メジャーバージョンが上がる毎に大きな設計変更が行われています(出典:https://ja.wikipedia.org/wiki/Laravel)。

  • Laravel 1: 2011年6月
  • Laravel 2: 2011年11月
  • Laravel 3: 2012年2月
  • Laravel 4: 2013年5月
  • Laravel 5: 2015年2月

Laravel 5.1では、初のLTS(Long Term Support)となり、3年間のサポートが提供されることが決まりました。しかし、SymfonyのLTSとは異なり、LTSでも機能追加が行われていたりします。また、現在の最新版は5.2です。

(3) エッジなターゲット

Laravelは、「そのバージョンがリリースされた時点で公式サポートされているPHP」を、動作対象バージョンの指標にしているようです。Laravel 5.1ではPHP 5.5.9以上が対象になっています。また、Laravelに最適されたPHP開発環境のHomesteadは、v0.4.0以降ではPHP 7.0がインストールされています。

Laravelリファレンスについて

Laravelリファレンスは、その名の通り「リファレンス」という色合いが強いです。以下が目次ですが、初心者向けは1章と2章です。8章はチュートリアル形式ですが、Laravelの基本機能を触ってみるというよりは、Laravelの機能を活かしつつ、最近採用が増えているレイヤードアーキテクチャの実践をやってみよう、といった応用的な内容です。

Chap.01 Laravelの概要
Chap.02 Laravelの基本
Chap.03 データベース
Chap.04 フレームワークの機能
Chap.05 フレームワークの拡張
Chap.06 テスト
Chap.07 実践的なアプリケーション構築
Chap.08 Laravelの実践

タイトルに「リファレンス」とあるとおり、通読する本というよりは、ざっと目を通して、後で必要になった時に調べる本だと思います。Laravelにどんな機能があるか眺めるには便利です。

また、サンプルコードも全てgithubで公開されています。第8章のサンプルコードなどは、書籍の方では解説が割愛されている部分でも工夫を凝らした実装がされていたりするので、一度眺めてみると良いと思います。

Laravelの優れた機能

個人的に気に入ったLaravelの機能をいくつか挙げていこうと思います。

マイグレーション

データベース定義をPHPソースコードで記述することができます。コードで記述されていることから、ロールバックが容易です。個人的に、DB定義はMySQL WorkbenchでER図を書いて、このER図に基いてSQLを作ることが多いです。この形式は、ドキュメント(ER図)からDB定義ができるという点では非常に便利ですが、ソースコードでDB定義が管理できることには別の便利さがあります。

Secure by defaultなクエリビルダ

これはSymfonyのORM(Doctrine)のクエリビルダとの比較になるのですが、LaravelのORM(Eloquent)は、より安全に書けるようになっています。

Doctrineのクエリビルダで単純にクエリを書くと以下のようになります。

この書き方には、潜在的なSQLインジェクションの脆弱性があります。eq()メソッドの第2引数の値はエスケープされず、プリペアードステートメントも使われないため、$nameにSQL文が入っていた場合はそのクエリが実行される可能性があります(Doctrineのソースコード)。

Doctrineでの正しい書き方は以下のようになります。この書き方だとプリペアードステートメントが使われます。

これに対して、Eloquentは以下の書き方でプリペアードステートメントが使われます。何も注意しなくても、デフォルトで安全に使えるようになっています。

FormRequestによるバリデーション

LaravelにはFormRequestという仕組みがあります。これは、コントローラーの手前でバリデーションを行う仕組みです。
FormRequestでは、各アクションに応じて、IlluminateFoundationHttpFormRequestクラスを拡張したクラスを作成します(titleを必須・最大文字数255、bodyを必須に設定)。

このEntryStoreRequestを使ったコントローラーの実装は以下のようになります。

バリデーションルールに合致していないリクエストが送られてきた場合、FormRequestが自動的にエラーのレスポンスを返します。バリデーションとエラー通知の責務をコントローラーから分離することができます。

Laravelのイマイチなポイント:メタプログラミングの多用

上述したように、Laravelには優れた機能が多くありますが、Laravelでは気持ちよくコードが書けないと感じることも多いです。その理由は、メタプログラミングの多用にあります。

Laravelの特徴の一つであるFacadeを使うと、以下のような記述ができます。

Config::get()は静的メソッド呼び出しですが、Configというクラスが存在するわけではありません。config/app.phpに以下のような設定がされています。

この設定に基いて、PHPのclass_alias関数によって「Config」というクラスの実体がIlluminateSupportFacadesConfigであると定義されています。このクラスからさらにサービスコンテナへの問合せが行われ、最終的にIlluminateConfigRepository::get()メソッドが呼び出されます。

このように複雑なメタプログラミングが使用されていることから、静的解析を主に用いているIDEとの相性は良くありません。ide-helperプラグインを用いて、クラス定義を静的に書き出すことでFacadeなどはIDEの補完が効くようになりますが、それでも限界はあります。以下は『Laravelリファレンス』8章のサンプルコードをPhpStormで開いているところのスクリーンショットですが、orderBy()に未定義メソッドの警告が出ています。

laravel_orderBy

ここで使用されているIlluminateDatabaseEloquentBuilder::where()は自分自身を返しますが、IlluminateDatabaseEloquentBuilderは自分が持っていないメソッド名が呼び出されると、__call()メソッド内部でIlluminate/Database/Query/Builderの機能を呼び出します。Illuminate/Database/Query/BuilderがorderBy()を持っているので、これが呼び出される、という流れになっています。

このように、頻繁に使用するメソッドでも補完が効かないことがあるのは地味につらいところです。

まとめ

『Laravelリファレンス』について、というよりはLaravelについての方が話が膨らんでしまいましたが、『Laravel』リファレンスはLaravel 5を使い始めるにあたって、まず手元に置いておきたい1冊だと思います。分厚い本ですが、リファレンス的に使うことを考えると、紙の方が良いと思います。

Laravel リファレンス[Ver.5.1 LTS 対応] Web職人好みの新世代PHPフレームワーク