PHPカンファレンス福岡2015発表レポート「CakePHP3ウォークスルー」 #phpconfuk

2015年6月27日に福岡で開催されたPHPカンファレンス福岡2015で「CakePHP3ウォークスルー」というタイトルで発表してきました。

このエントリでは発表の内容をご紹介します。
PHPカンファレンス福岡に東京から参加しての知見メモなどはこちらのエントリで。

発表のスライドはslideshareで公開していますのであわせてご覧ください。

CakePHPの歴史

CakePHPの歴史

CakePHP 1.x

CakePHPは、2005年3月に「Cake」という名前で最初のバージョンが、翌年、2006年3月に「CakePHP」としてバージョン1.0が公開されました。

この頃の時代背景として「Cake」公開の約半年前にRuby on Railsの最初のバージョンが公開され、CakePHP 1.0の4ヶ月前、2005年11月にRuby on Rails 1.0が公開された、そんな頃でした。

RoR以前にもいわゆる「フレームワーク」はあったのですが、基本思想の方向性が「フレームワークを設定によってシステムの設計に合わせて使おう」でした。具体的には、システムの設計をもとに、設定ファイルによってフレームワークに反映していました。

もちろん、このようなフレームワークも十分に便利で、十分に機能していました。

この様なフレームワークたちがしのぎを削っているところに彗星のごとくRoRが登場します。

最近は当たり前過ぎて改めて聞くことも無くなりましたがRoRは「設定より規約(Convention over Configuration. CoC)」を基本思想にしていました。これは従来の思想の逆で「システムの設計をフレームワークの規約に合わせよう」という思想です。
具体的には、設定ファイルを書くことなく、決まった場所に決まった名前、設計のファイルを置くことで、URLとコントローラの関連づけや、モデルとデータベースの関連づけをすることが出来ました。

RoRの登場は衝撃的でした。長谷川も一発でその虜になり、RoR 1.0公開直後からRoRを使用していくつかのシステム・サイトを作りました。

ただ、Ruby体験が初だったので、ちょとしたプログラムを書くのにも時間がかかり、苦労していました。

そんな折に「RoRクローンのPHPフレームワーク」としてCakePHPを知り、使ってみました。これが長谷川的にはドンピシャでハマりました。ディレクトリ構造は直前まで使っていたRoRそっくりですし、言語はPHPです。RoRを書いていた時は、全体の生産性が「RoRの生産性から自分のRuby能力を引いたもの」だったのですが、PHPのフレームワークであれば足し算にすることが出来ます。これ以来、ずっとCakePHPを使ってきています。

余談ですが、RoRの衝撃は非常に大きく、PHPだけでなく、当時はあらゆる言語でCoCなフレームワークが開発されはじめたと思います。

CakePHP 1.x 時代のPHP

CakePHP 1.x 時代は2005年〜2011年頃ですが、この頃はちょうどPHP5の最初のバージョンが公開され、PHP4が終演に向かっていく頃でした。

当時の個人Webページは、自身でHTMLやJavaScriptを書いて、共有レンタルサーバに置く、というスタイルが一般的でした。この様な背景で、PHPはPerlと並んで「掲示板」や「アクセスカウンター」など、Webページの機能的装飾としてのスクリプト言語として数多くのコードが書かれ、配布されていました。

PHPは複数のPHPバージョンを1サーバで共存させることが簡単にはできないため、共有レンタルサーバのサービス提供元は提供する1つのPHPバージョンを決定することになります。PHP4からPHP5の変更は結構大きく、そのままでは動かなくなるプログラムも多く存在していました。そのため、世の中のPHP5移行のスピードは遅く、「まだPHP5は早いよね」という雰囲気でした。

そんな中公開されたCakePHP 1.0はPHP4.3.2以上で動作しました。これは当時CakePHPを使う理由として非常に大きかったことをよく覚えています。

なお、CakePHPと並んで現在もメンテナンスが続いているSymfonyはCakePHP1.0から遅れること10ヶ月、2007年1月に公開されています。この時点でPHP5.0のリリースから2年半が経過しており、Symfony 1.0はPHP5以上サポートを選択していました。開発案件としては「CakePHPかSymfonyか」の様な議論をよくしていましたが、サーバの環境の制約でCakePHPが選択されることもままありました。

これは「PHP4.3.2以上という選択でCakePHPは得をしたよね」というお話です。ただ、PHP4は一応オブジェクト指向なプログラムを書くことが出来るものの、そのサポートは限定的でした。そのため、CakePHPではそれをプログラム上の「工夫」で補っているところがありました。この「工夫」は後のCakePHP2にも引きずっている様にみえるところもあり、PHP4をサポートするという選択の損得勘定は簡単では無いだろうな、とも思います。

CakePHP 2.x

CakePHP 1.0の公開から5年7ヶ月後の2011年10月、CakePHP初のメジャーバージョンアップであるCakePHP2が公開されます

CakePHP2はサポートするPHPバージョンをPHP5.2.6以降とし、晴れて「ちゃんとしたオブジェクト指向」の設計を獲得しました。ただし、モデルからのデータは配列として返され、取得したモデル名(テーブル名)が配列のキーとして含められていました。

CakePHP2は最初のリリースの後、3〜6ヶ月に1回のペースでアップデートが続けられ、2014年12月にはCakePHP 2.6が公開されました。

CakePHP 2.x 時代のPHP

CakePHP2時代は2011年10月から2015年3月頃までですが、この頃、CakePHPの外ではComposer 1.0.0-alpha1の公開や、コーディング規約 PSR−2、クラスのオートロード規約 PSR-4などが公開され、それらを採用するプロダクトは綺麗に、効率的な構成に変化していきました。

また、この頃のPHPはPHP5.3のクロージャや名前空間、PHP5.4のトレイトや配列の短縮構文など、他のモダンな言語で取り入れられている機能が取り入れられていました。

しかし悲しいかなPHP5.2.6以上をサポートとするCakePHP2ではそれらの今風な機能を利用することができませんでした。

言語機能については自分でプログラムを作る部分について勝手に使っていれば良いのですが、ComposerやPSR−4についてはそうもいかず、個人的にはそれらを前提として設計された他のフレームワークを見て羨ましく、また、なんとなく後ろめたい気持ちでいました。

CakePHP 3.x時代

そんな中、2015年3月に大きくモデルチェンジされたCakePHP3が公開されました。CakePHP3はサポートするPHPをPHP5.4以上とし、クロージャ、名前空間、トレイトといった今風の言語機能を使用して綺麗でモダンな設計になりました。また、CakePHP1の頃からの「とりあえず配列でなんとかする」設計ではなく、モデルまわり中心にオブジェクト化がされました。

CakePHP2 → CakePHP3の変化

ここからはCakePHP2 → CakePHP3で大きく変わったところを中心にその変更をご紹介します。

セットアップ方法の変化

CakePHP2時代は基本的にはCakePHPのWebページからzipファイルをダウンロードしてきて展開する、というのがセットアップの方法でした。

CakePHP2も後に、composerを使ったセットアップ方法ができました。ただ、composer install → bake としてプロジェクトを作成すると、プロジェクト中のいくつかのファイルが想定するパスが実態と合っていなくてエラーになってしまう、みたいな悲しい状態でした。(app/webroot/index.php, app/webroot/test.php, app/Console/cake.php3ファイルだけ修正すれば大丈夫です。)

CakePHP3ではCakePHPのプロジェクトテンプレートをcomposer経由で取得することが出来る様になりました。

$ composer create-project –prefer-dist cakephp/app cake3

このコマンドでは、以下の様に、cakephp/app からプロジェクトテンプレートをダウンロードし、composer installを実行しています。プロジェクトテンプレートにはCakePHP3や、それに必要なライブラリ群が含まれたcomposer.jsonが含まれています。

そのため、このコマンド1つでプロジェクトテンプレート、CakePHP3本体、CakePHP3に必要なライブラリがすべてインストールされます。

CakePHP3インストール

出来上がったプロジェクトディレクトリはこんな風になっています。

プロジェクトディレクトリ

エディタの設定を記述する.editorconfigファイルにはPSR-2の設定がされていたり、最初からCakePHP3に適切な.gitignoreファイルがあったりと、今風な作りになっています。

ディレクトリ構成 / PSR

ディレクトリ構成についても大きく手が入れられています。ここはシンプルなのでスライドにて。

プログラムルート

ビューテンプレート

設定ファイル

CakePHP3ではコーディング規約としてPSR-2、クラス配置(ローディング)規約としてPSR-4に準拠しています。

PSR-2は個人的に開きブレースの場所が好みでなく、CakePHP3がPSR-2に準拠すると聞いたときには「いやだなあ」と思っていました。でも、実際に書き始めたら1週間で慣れました。同じ思いの方も是非ガマンして書いてみてください。

モデル

CakePHP3ではモデルが最も大きく変わったところだと思います。

CakePHP2ではModelクラスでクエリを実行し、Modelクラスからは配列の形で結果が返されていました。それに対して、CakePHP3ではTableクラスでクエリを実行し、Entityオブジェクトで結果が返されます。

モデルの動作

CakePHP2では、コントローラからモデルのfind()を実行するとその時点でクエリが実行され、結果が配列の形でコントローラに返されていました。そのため、大きな配列がモデルからコントローラに、コントローラからビューに、と受け渡されている、であるとか、ビューで最終的には使わないクエリも実行されるといった問題がありました。

これに対してCakePHP3では、コントローラからモデルのfind()を実行した時点ではクエリが実行されず、Queryオブジェクトの形のでコントローラに返されます。このQueryオブジェクトをビューに受け渡してそこからEntityオブジェクトを取り出して使用します。

Table / Entity Object

オブジェクト化はパフォーマンスや設計のキレイさ意外にも、IDEでサジェストしやすくなるというメリットもあります。

サジェスト

ただ、このためにはIDEに型を伝えるアノテーションを書いてあげる必要があります。

アノテーション

CakePHP2ではモデルクラスのプロパティとして配列で表現していたバリデータもオブジェクトで表現する様に変更されています。
もちろんサジェスト可能。便利ですね。

バリデーションサジェスト

コントローラ & ビュー(含ヘルパ)

モデル & バリデータ以外にも多くの変更が入っています。

今回の発表ではCakePHP2で何がイケていなかったか、そしてそれがいかに今風に解決されたかと、モデル & バリデータがどの様に改善されたかを中心にCakePHP3の魅力をお伝えしたく、内容に含めませんでした。

まとめ

まとめ