綺麗に死ぬITエンジニア

私が「CakePHP 3」よりも「Laravel 5」を推したい理由

2017-07-04

現在、数多くのPHPフレームワークが登場しています。

ですが、私の周りでは、新規案件においては大体「CakePHP 3」か「Laravel 5」の二択になっています。この二つのフレームワークは、日本において、今現在PHPフレームワークの二強といってもいい存在ですね。

私はどちらのフレームワークもある程度使った経験があります。

そしてその結果、私の中では「CakePHP 3」よりも断然「Laravel 5」の方が優れているという結論が出ましたので、その理由を解説していきます。もちろん、好みの問題もありますので、フレームワーク選定の参考にしようとされる場合は、案件やチームのスキルを鑑みて総合的に評価してください。

自由なディレクトリ構成

これはチームによってはメリットにもデメリットにもなりうる要素ですが、基本的にLaravelは、PHPのソースコードを配置する際のディレクトリ構成(名前空間の構成)が自由です。

実際には、インストール直後の初期のディレクトリ構成のまま開発を進めることになると思いますが、既存のディレクトリ構成を変更したり、独自のライブラリクラスを追加したりする場合には、無理なくそれを実施することができます。

CakePHPの場合も、3系からは名前空間によるオートロードが可能となり、ライブラリクラスを追加する程度なら可能ではありますが、既存のディレクトリ構成を変更するのはフレームワークの特性的に無理があるのが現状です。もちろん、頑張ればできないこともないですが、フレームワークの規約から離れることになるため、現実的に採用は不可能でしょう。

大体の案件の場合、PHPのフレームワークに関する知識がある人間や、アーキテクチャーの策定ができる人間が、チームを引っ張っていくことになるかと思います。

そういう場合、CakePHPのようにガチガチにディレクトリ構成が決まってしまっているよりも、Laravelのようにある程度開発者が自由に決定できる余地が残されていた方が、後々応用でき、良い場合が多いです。

バリデーション処理の拡張性

CakePHPとLaravelでは、バリデーション処理の記述する場所が異なります。これは恐らく、CakePHPとLaravelで最も影響がある、最も違う点だと思います。

CakePHPでは、バリデーション処理をMVCで言うところのモデルに記述します。ところが、LaravelではMVCで言うところのコントローラーに記述します。

私は、経験上、バリデーション処理をモデルに記述すると不便な場合が多く、コントローラーに記述した方が可読性が上がり、合理的な場合が多いという結論に至っています。

バリデーション処理をモデルに記述する一番のメリットは、そのバリデーション処理を意識することなく使いまわせる点だと思います。しかしながら、バリデーション処理を意識せずに使いまわしたい場面なんて実際にはあまりありませんし、使いまわしたい場合もバリデーションルールを共有できる仕組みがあります。しかも、Laravelではバリデーション処理を簡単に記述できる仕組みが搭載されているので、バリデーション処理がファットコントローラーの要因になるということはないです。

例えば、Laravelではバリデーション処理を以下のようにコントローラーに記述します。

// コントローラーのメソッド
public function store(Request $request)
{
    $this->validate($request, [
        'title' => 'required|max:255',
        'html' => 'required',
        'published_at' => 'date',
    ]);

    $post = Post::create($request->all());
    $post->saveOrFail();

    return redirect()->route('posts.index');
}

上記は、入力値をバリデーションした後、その入力値からPostを作成し、ページをリダイレクトする処理となっています。$this->validate()$post->saveOrFail()で失敗があった場合は、そこで例外が投げられます。

コントローラーを見るだけで、バリデーション処理が走っていること、その後データを作成していること、ページをリダイレクトしていることがサッと見えてわかりやすいかと思います。

CakePHPの場合は通常、以下のようになります。

// テーブルクラス(モデル)
class PostsTable extends Table
{
    public function validationDefault(Validator $validator)
    {
        $validator
            ->requirePresence('title', 'create')
            ->notEmpty('title')
            ->maxLength('title', 255);

        $validator
            ->requirePresence('html', 'create')
            ->notEmpty('html');

        $validator
            ->date('published_at');

        return $validator;
    }
}

// コントローラー
public function store(Request $request)
{
    $posts = TableRegistry::get('Posts');
    $post = $posts->newEntity($this->request->getData());
    $posts->save($post);

    return $this->redirect(['controller' => 'Posts', 'action' => 'index']);
}

モデルの内部でバリデーション処理を記述する必要があり、他のバリデーションルールを用いたい画面がある場合は、その数だけ記述(validationXxxメソッド)が増えることになります。1画面でしか使わないルールであったとしても、それがモデルクラスに影響を与えます。これは処理が密結合になる要因の一つと言えるでしょう。

コントローラーでパッと見、バリデーション処理を行っているように見えず、どこでバリデーション処理が行われるのかわかりにくい点も、私はあまり好きではないです。

また、CakePHPではモデルと関係のないバリデーション処理を行いたい場合は、フォームクラスを作成する必要があり、これまた手間であることは間違いないです。

なお、CakePHPでもValidatorを利用すれば、Laravelと同様にコントローラー内で処理させることも可能です。しかし、Laravelほど簡単に記述できるものではありませんし、何よりCakePHPにおける一般的な手法ではなく、通常のモデル内部のバリデーション処理をスキップさせる処理を記述する必要があるため、混乱を招く可能性が高いです。

ファイルアップロード処理の簡単さ

Webアプリケーションを実装する上で面倒な処理の一つに「ファイルアップロード処理」があります。

CakePHPには、ファイルやディレクトリを操作することができるFileクラスやFolderクラスこそ用意されていますが、アップロードされたファイルを処理するインターフェースは用意されていません。

近年ではアップロードされたファイルをローカルディスクではなく、AWSのS3等のクラウドストレージに保存するケースも多くなってきました。

CakePHPを用いる場合には、それらのアップロード処理を自分で実装したり、外部のプラグインを使って実装する必要があります。それに加え、外部のプラグインを用いる場合、設定値などで応用できないパターンも多く、特定のケースでは利用できないなんてこともあったりして、なかなか一筋縄ではいかないことが多いです。

その点、Laravelではファイルストレージ用のインターフェースが公式で用意されており、数行でアップロード処理が実装できるのはもちろん、パラメーターとプラグインによって保存先をローカルストレージからクラウドストレージに切り替えることもできます。

また、CakePHPには元々ファイルアップロード用のディレクトリが存在しておらず、多くの場合webroot(Webコンテンツ用の公開ディレクトリ)にそのまま保存するような形になりますが、Laravelには元からアプリケーションデータ保存用のstorageディレクトリが用意されているので、ディレクトリ構成を乱すことなく実装可能です。

この辺は単純に機能として、CakePHPよりもLaravelが優れている点ですね。

習得コストの差 / コアコードの可読性

最後に、それぞれの習得コストの差について記します。

CakePHPは、規約が厳しく、また独自の概念が多く存在します。規約を覚えてルール通りに開発していけば、結構早く開発できます。しかしながら、独自の概念が多いので、他のフレームワークへの応用ができない場合が多く、フレームワーク自体の応用が難しいです。

つまり、CakePHPはちょっと変わったことをやるのが大変だということです。

一方Laravelは、ディレクトリ構成が複雑で、なおかつ高機能なため、機能についての学習コストは高いですが、CakePHPのようなガチガチの規約に惑わされることがないので、比較的応用が利きます。

世の中、色々な案件がありますから、時々マニアックな動作をさせたくなることもあるでしょう。

そんなとき、CakePHPではガチガチの規約と複雑なコアコードに悩まされることになります。一方、Laravelでは柔軟に色々なアプローチで対応することができるでしょう。コアコードもLaravelの方が規約が少ない分簡単に読めます。

やり初めの学習コストはCakePHPの方が少しだけ低いかな、とは思いますが、やりたいことが増えてきたときの学習コストはLaravelの方が断然低い、と評価しています。

まとめ

「CakePHP 3」と「Laravel 5」には大まかに上記のような差があります。

これ以外にもORMやviewファイル等沢山違いはありますが、特に気になる、私的に重要な部分だけを抜き出しました。参考になれば幸いです。

最近ではシェア的にも後発のLaravelが先発のCakePHPを抜いてきており、やはりいろんなケースにおいてLaravelの方が使いやすいという評価がされ始めてきているものと思います。そして、シェアが増えたということは、付随してプラグイン等の開発も活発だということです。

と、いうことで、「CakePHP 3」と「Laravel 5」で悩んでいる方、これからは「Laravel 5」を使っていきましょう。

筆者について

フリーランスエンジニアとして活動している、「もりやませーた」です。

筆者のTwitterはこちら。記事に関するご意見等はTwitterの方へお寄せください。

その他業務に関するお問い合わせは、こちらのページをご覧ください。

PHP Laravel