ランサーズ(Lancers)エンジニアブログ > PHP > CakePHP > CakePHP3→CakePHP4にmigrateしてみた

CakePHP3→CakePHP4にmigrateしてみた

blog_admin|2019年12月25日
CakePHP

CakePHP Advent Calender 2019 最終日の記事です。

SREチームの金澤です。

2019/12/16にCakePHP4がリリースされました。

ランサーズでは、CakePHP2.10の現システムをCakePHP3に移行中ですが、
同時に、管理画面のソースを別リポジトリに分割し、
CakePHP4で新規構築するプロジェクトも進めています。

CakePHP3で開発をしていたのですが、
CakePHP4が正式リリースされたので、CakePHP4にmigrateしました。
今回、その手順を記録しておきたいと思います。

composer.jsonのCakePHP4対応

CakePHP4.0にアップグレードするためにcomposer.jsonを修正します。

案の定ですが、単純に

"cakephp/cakephp": "^4.0",

として、composer updateしても依存関係でエラーとなってしまいました。

$ php composer.phar update
Loading composer repositories with package information
Updating dependencies (including require-dev)
Your requirements could not be resolved to an installable set of packages.

  Problem 1
    - maiconpinto/cakephp-adminlte-theme 1.1.0 requires cakephp/cakephp ~3.0 -> satisfiable by cakephp/cakephp[3.0.0, ... , 3.8.7, 3.x-dev] but these conflict with your requirements or minimum-stability.
    - maiconpinto/cakephp-adminlte-theme 1.1.0 requires cakephp/cakephp ~3.0 -> satisfiable by cakephp/cakephp[3.0.0, ... , 3.8.7, 3.x-dev] but these conflict with your requirements or minimum-stability.
    - Installation request for maiconpinto/cakephp-adminlte-theme ^1.1 -> satisfiable by maiconpinto/cakephp-adminlte-theme[1.1.0].

$

そのため、まずcakephp/appのcomposer.jsonをベースにCakePHP4.0をインストールし、
これをベースに必要なツールを1つづつ追加していくことにしました。

結果、CakePHP用のAdminLTEがCakePHP4に対応していないことが判明しました。
(冒頭のエラーの通りですが)

AdminLTEのCakePHP4対応

CakePHP用のAdminLTE
https://packagist.org/packages/maiconpinto/cakephp-adminlte-theme
は、CakePHP3専用で、現状CakePHP4には対応していません。

そのため、Githubリポジトリ
https://github.com/maiconpinto/cakephp-adminlte-theme
をforkしてCakePHP4に対応させることにしました。

githubリポジトリのプロジェクトをcomposerで読み込む

forkしたAdminLTEをCakePHP4.0に対応させ、自社のGithubリポジトリ
https://github.com/LancersDevTeam/cakephp-adminlte-theme
で管理します。

forkしたリポジトリのcomposer.jsonのnameを変更します。

  "name": "lancers/cakephp-adminlte-theme",

管理画面プロジェクト側のcomposer.jsonで、そのnameとforkしたgithubリポジトリを呼び出すように設定します。

{
    "repositories": [
        {
            "type": "vcs",
            "url": "git@github.com:LancersDevTeam/cakephp-adminlte-theme.git"
        }
    ],
    "require": {
...
        "lancers/cakephp-adminlte-theme": "dev-master"
    },

関連ツールがCakePHP4に対応するまでは、
こうやって自前でCakePHP4に対応し、githubで管理しておく必要がありそうです。

CakePHP4.0対応のPRを出す

AdminLTEのCakePHP4化についてはPRを出しておきました。
https://github.com/maiconpinto/cakephp-adminlte-theme/pull/93

※CakePHP4版はPHP7.2以上が必須になり、PHPUnitも8.3.3以上が必須になるため、
(PHP5.4やPHP5.6をサポートする)CakePHP3版との共存は難しそうです。
ので、マージされるのであれば、メジャーバージョンアップでの対応になるかも知れません。

Upgrade ToolによるMigrate

4.0 Upgrade Guideに従って、Upgrade Toolによるアップグレードを行います。

※AdminLTEのCakePHP4バージョンアップの際も利用しました。

CakePHP Upgrade Tool

4.xブランチに切り替えて、以下のコマンドを実行すると、

$ ./bin/cake upgrade file_rename templates /path/to/app/
$ ./bin/cake upgrade file_rename locales /path/to/app/

以下の変換が行われます。

・src/Template → templates
・ctp → php
・src/Locale → resource/locale

※これに伴い、app.phpのpathsの設定も変更する必要があります。

config/app.php

        'paths' => [
            'plugins' => [ROOT . DS . 'plugins' . DS],
            'templates' => [ROOT . DS . 'templates' . DS],
            'locales' => [RESOURCES . 'locales' . DS],
        ],

Rector

composer.jsonにrectorを追記してインストールします。

    "require-dev": {
...
        "rector/rector": "*"
    },

4.0 Upgrade Guide に記載されていた、cakeコマンドで起動する方法がうまく行かなかったので

$ bin/cake upgrade rector --rules cakephp40 src
Unknown command `cake upgrade`. Run `cake --help` to get the list of commands.

Other valid choices:

- help
- version
- i18n
- routes
- server
- console
- bake all
- bake
- migrations
- compile

rectorコマンドを直接起動しました。

$ ./vendor/rector/rector/bin/rector process src --set cakephp40
Rector v0.6.0

  0/66 [░░░░░░░░░░░░░░░░░░░░░░░░░░░░]   0%
PHP Fatal error:  Declaration of App\Model\Table\FaqsTable::initialize(array $config) must be compatible with Cake\ORM\Table::initialize(array $config): void in /path/to/app/src/Model/Table/FaqsTable.php on line 98
$

親クラスであるCakePHP4 CoreのTableクラスと引数、戻り値が一致しないと怒られたので
これを修正していきます。(これを自動的に修正して欲しいのですが。。)

結果、以下の修正を行う必要がありました。

public function initialize(array $config)

public function initialize(array $config) : void

public function buildRules(RulesChecker $rules)

public function buildRules(RulesChecker $rules) : \Cake\ORM\RulesChecker

public function validationDefault(Validator $validator)

public function validationDefault(Validator $validator) : \Cake\Validation\Validator

public function beforeFilter(Event $event)

public function beforeFilter(EventInterface $event)

cakephp/app のCakePHP4対応

プロジェクトの以下のディレクトリをCakePHP4に対応させる必要があります。
(PHP7.2に対応に伴う引数の変更や戻り値の型変更など)

・config
・src
・templates
・webroot

※結局、https://github.com/cakephp/app のCakePHP4対応版を上書きし、
個別の実装差分を記述し直しました。

始まったばかりのプロジェクトのため、それほど手間ではありませんでしたが
既にCakePHP3の実装が進んでいるプロジェクトは別のアプローチが必要かも知れません。

stableバージョンにしたいが。。

現状のcomposer.jsonは以下の記述があるため、CakePHP 4.x-devがインストールされます。

    "minimum-stability": "dev"

stable版である CakePHP4.0.0 をインストールするにはこの記述を削除する必要がありますが、
cakephp/migrationsも削除する必要がありました。
このツールはrectorが利用しているため、完全に移行が終了してから削除したほうが良さそうです。

"cakephp/migrations": "3.0.0-beta1",

また、bakeも2.0から1.2.8までバージョンを落とす必要がありました。

        "cakephp/bake": "^1.2",

bakeのバージョンを1に落とすと、さすがにCakePHP4では使えなさそうなので、まだ

    "minimum-stability": "dev"

の設定は外せなさそうです。

最後に

今回、開発中のプロジェクトをCakePHP3からCakePHP4にmigrateしてみましたが、
周辺ツールがまだCakePHP4に追いついておらず、
今のタイミングで完全移行するのは時期早尚かも知れません。

ただ、ランサーズ本体のCakePHP2→4移行については、
段階的に移行しているため、できることならCakePHP2→4へジャンプアップしたいところです。
(それを実現するためには、PHPUnitの共存等も実現する必要がありますが)