CakePHP使いが今更ながらLaravelに乗り換えた話

CakePHPに対する想い

およそ3年前に、CakePHP Ver3を深く理解しようという想いもあり、着手したのがTuListというサービスです。

CakePHP Ver3を採用した理由としては下記が挙げられます。
(上から順に重要度が高い)

  • フレームワークとしての完成度高い
  • githubでのコミット頻度が高い
  • 日本語での情報量が多い

しかし、ここ1年ほど状況をウォッチしてきたところ、上記3点を含めかなりLaravelが優位になってきているように思います。

特にgithubでのコミット頻度に関してはCakePHPの優位性は、ほぼなくなってきたと言っても過言でないくらいの状況となってきました。

参考
Laravelのコミット頻度(グラフ)

[Laravel]執筆時点のグラフ
[Laravel]執筆時点のグラフ

CakePHPのコミット頻度(グラフ)

[CakePHP]執筆時点のグラフ
[CakePHP]執筆時点のグラフ

また、2017年に開催されたCakePHPの公式カンファレンスでは、CakePHP4について下記のように公表しています。

現在のスケジュールでは、これらのリリースの最初のベータ版は2017年後半から2018年初頭にリリースされます。

bakery.cakephp.org のGoogle翻訳結果を一部抜粋

しかし、最初のベータ版が出たのは2019年6月です。
(最初のα版は2019年4月)

時は既に2019年9月で、正式リリースはいまだにされていません。
この遅れには大きな失望を感じています。

Laravelに対する想い

CakePHPの公式カンファレンスにてCakePHP4について語られた頃、既にGoogleトレンド上ではLaravel優位となっています。

参考:GoogleTrendsでの比較

それでもこのタイミングでは、githubのコミット頻度からCakePHP4での挽回を期待し見守ってきました。

そんな私がLaravelへの乗り換えを決定づけたのは、Laravelのバージョンアップサイクルです。

参考:Laravel Release Process (Laravel公式ブログ)

約2年周期で安定的にLTS(*1)をリリースしているという事実は、長期的にサービスを提供する上では無視できません。

さらに、2019年9月3日には最新のLTSであるバージョン6が正式にリリースされました。

しかも、このリリースではバージョニングルールが変更され、マイナーバージョンアップでは破壊的なバージョンアップをしないことにもなりました。

Laravelフレームワーク(laravel / framework)パッケージは現在、
セマンティックバージョニング標準に準拠しています。
これにより、このバージョン管理標準に既に準拠している他のファーストパーティLaravelパッケージとフレームワークの一貫性が保たれます。
Laravelのリリースサイクルは変更されません。

Laravel 6 Is Now Released のGoogle翻訳結果を一部抜粋

Laravel6が公開されたことで、冒頭で挙げた「CakePHP Ver3を採用した理由」におけるCakePHPの優位性は、重要度が最も低い日本語による情報(*2)のみとなりました。

Laravelの使用感

上記のようなことを考えている矢先、職場にて技術選定含め丸っと一人で対応するチャンスがあったため、Laravelを採用して実装してみました。

Laravelを使ってみたところの所感を端的に表現すると「良くも悪くもPHPらしいフレームワーク」です。

CakePHPと比較した所感をもう少し掘り下げてつらつらと並べてみます。

良いところ

  • 関数ベースで実装されているヘルパーがめっちゃ便利
    • request()とかroute()とか
  • routeの設定が簡潔でわかりやすい
  • routingをコマンドで確認できて素晴らしい!
  • テンプレートエンジンのBladeがとても良い!
  • PhpStormのLaravelプラグインが良い!

イマイチなところ

  • アーキテクチャがOOP(*3)っぽくない
    • 一部、めちゃくちゃと呼べるレベル(後述)
  • DTAとDAO(*4)が同一であることに違和感
  • 公式のチュートリアルがバージョンに追いついていない
  • デバッグ関連が貧弱
    • CakePHPのDebugKitが秀逸すぎる

Laravelのアーキテクチャ

「OOPっぽくない」こと自体は悪いことではないです。
関数として実装しているヘルパーは、OOPにこだわらない結果の実装でありOOPっぽくないことによる恩恵だと思います。

一方で、「一部、めちゃくちゃと呼べるレベル」というものを挙げました。
一部というより一点と言ったほう正しいかもしれません。

具体的にはModelに実装されている下記マジックメソッドに激しい違和感を感じます。


    /**
     * Handle dynamic static method calls into the method.
     *
     * @param  string  $method
     * @param  array  $parameters
     * @return mixed
     */
    public static function __callStatic($method, $parameters)
    {
        return (new static)->$method(...$parameters);
    }

staticな呼び出しに対して対象となるメソッドが存在しない場合、インスタンスを生成して、インスタンスメソッドを呼び出すという仕様のようです。

おそらく、呼び出し利便性を考慮しての実装でしょうが、「OOPは役割分担こそが大事」という認識を持っている私からすると、この実装はありえないの一言につきます。

それは、私が実装したシステムでは利用できないようにオーバーライドするくらい気持ちが悪いものです。

以下はAppModelというクラスを作成し仕様変更した実装です。


    /**
     * インスタンスを生成する
     *
     * @return static
     */
    public static function gen()
    {
        return new static();
    }

    /**
     * @param string $method
     * @param array $parameters
     * @see Model::__callStatic
     * @return mixed
     */
    public static function __callStatic($method, $parameters)
    {
        throw new DeprecatedException('このシステムではstaticなマジックメソッドは利用できません。代わりにインスタンス生成後にインスタンスメソッドとしてコールしてください。');
    }

使い方としては下記のように変更となります。

Before

User::whereId($id);

Afater

User::gen()->whereId($id);

利便性を下げてまで実装するものなのか?という意見も聞こえてきそうですが、ここまでしたくなるほど気持ちが悪い仕様でした。

まとめ

個人的にフレームワークはどこまで言ってもツールとしての域を出ることはなく、どのフレームワークを使うのかは手段の選択に過ぎません。

LaravelにはLaravelの良さがあり、CakePHPにはCakePHPの良さがあります。

今回、Laravelを利用する機会にも恵まれ結果的に両刀使いになることができ、個人的にはハッピーな結果となりました。

PHPのフレームワークは歴史的にも色々あり、日本の歴史に例えるとCakePHPが豊臣秀吉ならLaravelは徳川家康のような存在と感じます。

ここまで差がつけられてしまった現状では、CakePHP4がリリースされたとしても巻き返すのはかなり苦しいのではないでしょうか?

とはいえ、私の気持ち的にはまだまだCakePHPびいきです。

CakePHP4のリリースが追い風となり、再びPHPフレームワークのレジェンドになることを密かに願っています。

補足

*1 LTS:
Long Time Supportの略。
2年間という長期にわたり公式サポートするバージョンのこと。

*2 CakePHPの日本語に対する優位性:
CakePHPの公式ドキュメントは日本語にとても優しい。

*3 OOP:
Object Oriented Programmingの略。
オブジェクト指向プログラミングのこと。

*4 DTAとDAO:
Data Transfer Object と Data Access Objectの略。
一般的には分離されることが多い。