KimuraTweetこんにちは。リスペクトの木村です。CakePHPで運用しているサイトがいくつかあるのですが、その一部について1.3から2.6へアップグレードする機会がありました。フレームワークのコア部分のアップグレードというと何かしらのトラブルが発生する印象があります(メジャーバージョンアップなら尚更)が、例に漏れずすんなりと終わる事はありませんでした・・・。そこで、今回はアップグレードの中で行った作業やすんなり行かなかったポイントについて、解決策と合わせてご紹介したいと思います。アップグレードに踏み切った理由そもそも、何故アップグレードに踏み切ったか、という所を簡単にご紹介します。諸事情ありますが・・・オンプレミスから、クラウド(AWS)へ移行する事になったApacheやPHPといったミドルウェアのバージョンが上がったり、サーバ構成が変更されるため、プログラムをある程度整理したいリファクタリングもしなければならないそもそも1.3系は3.x系のリリースに伴いサポート終了なので、今後の事を考えると2.x系もしくは3.x系へ上げなければならない大体はこんな理由です。ちなみに、1.3系のままでも一応動きます。コア部分の改修が必要になってくるのではないかという点や、上記のリファクタリングの作業を行う上で、フレームワーク側やPHP側の新機能に合わせてリファクタリングを行った方が良いのではないかなど、色々検討した結果、リファクタリング前にまずはアップグレードを行う事になりました。3.xではなく2.xにした理由ちなみに、CakePHPは今回アップグレード対象の2.6ではなく、3.0が最新版です。「せっかくなので最新の3.0へアップグレードするのが良いのではないか?」とは思いましたが、主に次のような理由で断念しています。2.xであればある程度慣れているが、3.xはリリースされたばかりのためある程度調査が必要1.3→2.xに比べて、変更されている部分がかなり多く、工数が大幅ににかかることが予想された1.3→2.xであればアップグレードシェル(ここに参照リンク)があるため、ある程度自動化されているが、1.3→3.xへ上げる手段は用意されていないそのため、全て手動もしくは、一旦2.xを経由してアップグレードする必要があるさらに、構造が特殊(後述)なため、想定しているよりも工数が掛かる可能性も結局2.xを経由する必要がありそうだったり、使い慣れてない3.xへ移行して何かあるよりは、安定していて使い慣れている2.xへの移行が最適だろう、という事で今回は2.6への移行となりました。上で「特殊な構造」と書きましたが、アップグレード前のアプリケーション構造はこんな感じでした。...どれぐらい特殊かお分かり頂けますでしょうか。本来、1.3系は2.x系のようにマルチアプリケーションに対応していないのですが、index.phpを書き換えて、アプリケーションの読み込み先を動的に変更させていました。同じ構造のフォルダ(controllersやmodels)が広がっている、という構造になっていました。アップグレードの主な作業+ポイント前提条件を説明した所で、早速作業とそのポイントについて説明します。今回は、2.0への移行ガイドを参考にしながら、次の作業順でアップグレードの作業を進めていました。大体はこの手順で良いはずなのですが、参考にされる際は手元の環境に合わせて調整して下さい。お次は、各作業の中で躓いたり調整が必要だった部分についてご紹介します。基本ではありますが、まずは不要なファイル/フォルダが無いかどうかを確認し、不要であれば削除しておきます。アップグレードやその後の作業に掛かる手間が少なくなるのはもちろんですが、後ほど使用するUpgradeShellは全てのファイルを探索してリネームや調整を行うため、時間の短縮に繋がります。整理する流れでシステム構造を改めて確認できるため、構造も整理する事で作業の効率化にも繋がります。Controller/Model/Viewや、利用しているComponent/Helperなんかは本当に全て使用しているかどうかを予め確認しておくと安心です。今回は、改めて確認すると利用していないもの、Git化前のバックアップ用ファイルや実験用の別名ファイルなんかが見つかったので、そこそこ整理しています。前から整理しておけばこうはならなかったはずですが・・・いい機会だと思って削除しました。1.3系プラグインはそのままでは2.xに対応していないプラグインも注意が必要です。プラグインの構造はapp下と同じのためか、1.3系向けのプラグインはそのままでは2.x系では使用できません。簡単な物であれば自分で調整する、というのも手ですが・・・やはりアップグレードが提供されていればそれを利用しましょう。cake_ktai_libraryのように2.x系の動作確認は古いバージョンまで、という場合があるのでこれも注意が必要です。可能であればプラグイン回りのコードは無効化しておき、アップグレード後に対応版を導入して再度動作を確認するという手段が理想的です。今回は利用していたプラグインのほとんどが2.x向け(対応?)ではありませんでした。そのプラグインの中でも使用している部分は一部だけでしたので、その部分と同じ動きをするようなプラグインを自作して対応しています。app/index.phpやapp/webroot/index.phpを2.xのものに上書きするアップグレード手順のサイトには記載されていませんが、app/index.phpやapp/webroot/index.phpの中身も若干変化しています。触らずとも大丈夫なのですが、念のため行っておいた方が良さそうです。今回のようにindex.phpの改変によるマルチサイト化が行われている場合は、そのままではUpgradeShellが動作しないため上書きが必須です。UpgradeShellによるファイル移動は万全ではないここまででUpgradeShellを実行する準備は整っているはずです。前の状態に戻せるようにしておくため、バックアップを取っておきます。変換後に、以前どんな構造だったかが速やかに確認できるという点でも有用なので、忘れずに取っておきます。実行前には–dry-runオプションを付与してどんなリネームや移動が行われるかを予めチェックしておきます。大体はこの通りの結果になるので、どんなリネームや移動が行われるかを確認しておきます。準備が整った段階でいざ実行しますが、この段階でエラーが発生し、変換が中途半端な所で止まってしまう場合があります。コンソールの結果から正常に終わっているかどうかを確認し、エラーで失敗していた場合はGitの管理で戻したり、バックアップから復元するようにします。今回遭遇したのは「ファイルやフォルダのリネームが正常に行われない場合がある」というものでした。Windows環境下で実行したせいかもしれませんが、先頭の文字を大文字に変換するだけのリネームに失敗している事が多めでした。view→Viewsでは成功しますが、view→Viewでは失敗する、という感じです。これは、Windowsが大文字小文字を区別しない仕様でため、同じフォルダ名と認識されてリネームに失敗しているためです。Mac/Linux環境下で発生する事は少ないのですが、対象ディレクトリをVagrantの仮想マシンでマウントしていて、そこに対してUpgradeShellを実行する場合も発生していました。回避方法としては、Gitによるバージョン管理が行われていれば–gitオプションを付与する事でgitを利用したリネームや移動が行われるため、付与する事で正常に実行できます。万が一失敗しても、Git上からアップグレード前の状態に戻せるため、安心です。ちなみに、今回のようにアップグレードするサイトがマルチサイト化している場合は、app下のディレクトリを一階層上げてから実行しましょう。ファイル内部のリネームも万全ではないUpgradeShellの実行時はファイルやフォルダのリネームに加えて、ファイル内部の調整も行われます。なるため、この書式に調整されます。UpgradeShellによるリネームのタイミングでは、その変数がModelかどうかの確認をしていないため、各種Helperのオーバーライドなどをしていて同じ命名規則の変数が存在する場合、その部分も上記の規則に従ってリネームされます。変更しておくか、Upgradeshellの実行後に$this->が付けられた部分を一通り確認し、余計な所まで変換されていないか確認しておきます。設定のアップグレードは行われないこれも当然ですが、設定回り(Config以下)の内容についてはアップグレードされません。core.phpやbootstrap.php、database.phpでは記述が変わっていたり、そもそも使用できなくなっているオプションが存在します。そのため、2.x用の設定を確認しながら、同じような設定になるよう調整を行います。手動で調整が必要な部分もある設定の他にも手動で調整する部分が多々存在するため、深いカスタマイズや変わった使い方をしている所は特に注意が必要です。独自のExceptionRendererを作成し、予めそれを呼び出すようにする必要がある特に、エラー表示回りやModelを呼び出す際の動作は使用している部分が多いので特に注意する必要があります。このあたりは、2.0への移行ガイドに書いてあったり、書いてなかったりします。必要なライブラリはComposer経由でインストールする、という場合が最近は多いと思います。app/Vendorやapp/Pluginに導入する場合はそのままで良いのですが、appと同ディレクトリにあるvendorsやpluginsに導入するという場合は注意が必要です。付かないディレクトリにインストールされるため、そのままではCake側で自動でロードされません。そのため、自動でロードされるよう調整を行う必要があります。Pluginの場合composer.jsonに次の記述を追加します。http://qiita.com/matsuoshi/items/fc105ce011a4a868879cこうする事で、CakePHPのPlugin(とPackagistに登録されているもの)はpluginsにインストールされるようになります。Vendorの場合この場合は公式ドキュメントにも書いてありますが、次の記述を追加します。true);1行目でautoload.phpを読み込んでいますが、これだけですと問題が発生します。そのため、2行目でCakePHPのオートローダーを一旦削除し、3行目で再度登録する事でComposerよりも先に評価されるようになります。おわりにCakePHPアップグレードの際の作業やハマったポイント、ちょっとした調整点をご紹介しました。実際に作業を進めてみると、何か問題があった際に解決しようとして調べてみるのですが、アップグレードしてみたという事例がそんなに多くないせいか、トラブル解決に若干手間取ってしまった感じがあります。基本的な事項はドキュメントや2.0への移行ガイドに書いてありますが、そこから発展した作業が必要な場合があるのでそこには注意が必要です。CakePHPのお作法に則ってマジメに作っていればこんなに困る事は無かったとは思いますが・・・大抵のサイトはどこかで引っかかってしまうのではないでしょうか。この記事が、アップグレードに困っている方のお役に少しでも立てれば幸いです。navigationマイナー?なSSHクライアント6選を使って比べてみたPHP7がリリースされたのでCakePHPの各バージョンが動作するか検証してみた株式会社リスペクトという、仙台・東京に拠点を持つ会社のシステム部門のブログです。プログラミングやシステム運用のノウハウなどを公開していきます。