CakePHP2 から CakePHP4 への移行について (2)


前回は CakePHP2 から CakePHP4 の移行準備として、Cakephp2 側のソースのリファクタリングについて書きました。この時点でだいぶ見た目は CakePHP4 のコードに近い状態となっています。今回は CakePHP2 のソースを CakePHP4 の仕様に合わせて一括変換を行うコンバータの考え方について書きます。

小規模かつCakePHP2版のソースのメンテナンスの継続を前提としたプロジェクトを移行対象としており、他のシステムの移行に対して参考にならない可能性があります。ビヘイビア、コンポーネント、ヘルパー、プラグイン、シェル、テストは移行対象としていません。また作成したコンバータのソースは、特定のプロジェクトの移行を目的としており、汎用性がないため、公開いたしません。

今回のコンバータの作成の目的は、ファイル名やコード内の文字列の単純な変更を自動化することです。具体的には以下のことを行います。

  • ディレクトリ構成の変更
  • ファイル名(拡張子)の変更
  • ソースファイルの分割
  • ソース内のモデル名を単数形から複数形に変換
  • ソース内の文字列の一括置換

まず CakePHP2 のソースを CakePHP4 のディレクトリ構造、ファイル形式に合わせて変換し、その後ソースの内容を CakePHP4 に仕様に合わせて変換します。モデル周りのソースは構造が大きく異なるため、bake にてコードを再作成し、個別に移植することとします。コンバータはあくまでの手作業を減らすためのもので、全てのコードを変換するわけではありません。全体のコードの6割を自動変換することを目標とします。

ディレクトリ構成の変更

CakePHP4 のディレクトリ構成は CakePHP2 に比べてより細分化されています。具体的には以下のように異なります。

コンバータでは CakePHP2 のソースを CakePHP4 のディレクトリ構造に合わせてファイルをコピーします。

コントローラファイルの変更

CakePHP2 ではユーザ向けのアクション用のクラスと、管理者向けアクション用のクラスがモデル単位で一つのファイルとなっており、admin_edit のようにメソッド名で管理者向けのアクションを指定できるようになっていました。CakePHP4 ではユーザ向けと管理者向けのクラスは分離され、Admin ディレクトリに配置されます。そこでコンバータでは CakePHP2 のソースをアクション単位で分割し、admin のついていないアクションメソッドはユーザ向けとクラスファイルに、admin のついているアクションメソッドは管理者向けのクラスに書き込み配置するようにします。

CakePHP2 のコントローラ

  • Controller/UsersController.php

CakePHP4 のコントローラ

  • src/Controller/UsersController.php (ユーザ向けクラス)
  • src/Controller/Admin/UsersController.php (管理者向けクラス)

テンプレートファイルの変更

CakePHP2 ではテンプレートファイルが View ディレクトリに配置されていましたが、CakePHP4 ではビューディレクトリにはクラスのみが配置され、テンプレートファイルは templates に配置するようになっています。またコントローラと同様、templates も ユーザ向けと管理者向けが分かれているため、それぞれのディレクトリにファイルをコピーします。また CakePHP2 ではテンプレートファイルの拡張子は .ctp をなっていましたが、CakePHP4 では .php となっています。コンバータでファイルのコピーと合わせて全てのテンプレートファイルの拡張子を .php に変更します。

CakePHP2

  • View/Contents/index.ctp
  • View/Contents/admin_index.ctp

CakePHP4

  • templates/Contents/index.php
  • templates/Admin/Contents/index.php

モデル名の変更

CakePHP2 ではソース内のモデル名が、User、Content 等と単数形となっていましたが、CakePHP4 では Users、Contents と複数形となっています。そこでモデル名の対応表を作成し、ソース内のモデルを単数形から複数形へと一括置換を行います。

モデル名の対応表(TAB区切り)

Content    Contents
Content    Contents
Content	Contents
Course	Courses
Group	Groups
Info	Infos
Log	Logs
Record	Records
Setting	Settings
User	Users
ContentsQuestion	ContentsQuestions
RecordsQuestion	RecordsQuestions
UsersCourse	UsersCourses
GroupsCourse	GroupsCourses
InfosGroup	InfosGroups

置換前

$this->User->xxx();
$xxx['User']['xxx'];

置換後

$this->Users->xxx();
$xxx['Users']['xxx'];

ソースの内容にもよりますが、「->Model->」 を 「->Models->」 へ、「’Model’」を「’Models’」へ置換することによって大部分が対応できるのではと思います。

文字列の一括置換

CakePHP2 と CakePHP が標準クラスやメソッドの名称変更が多くあります。単純に置き換えれるものを対応表にして、それを元に文字列の一括置換を行います。対応表はコントローラとテンプレートファイル、別々に用意しました。この対応表を充実させることで、コンバータの精度を向上させることが可能です。

コントローラファイルの置換文字列の対応表(TAB区切り)

function admin_	function 
App::uses('AppController', 'Controller');	namespace App\Controller;
->admin_	->
('admin_	('
find('first'	find()->first()
exists($question_id)	exists(['id' => $question_id)
App::uses('AppController', 'Controller');	namespace App\Controller\Admin;
find('count')	find()->count()
'conditions' =>	->where(
function admin_	function 
App::uses('AppController', 'Controller');	namespace App\Controller;
->admin_	->
('admin_	('
find('first'	find()->first()
exists($question_id)	exists(['id' => $question_id)
App::uses('AppController', 'Controller');	namespace App\Controller\Admin;
find('count')	find()->count()
'conditions' =>	->where(
'order' =>	->order(
'limit' =>	->limit(
$this->layout = '';	$this->viewBuilder()->disableAutoLayout();
admin_record	record
admin_edit	edit
(Exception	(\Exception
beforeFilter()	beforeFilter(\Cake\Event\EventInterface $event)
kind']	kind
status']	status
created']	created
modified']	modified
id']	id
title']	title
name']	name
score']	score
sec']	sec
understanding']	understanding
password']	password
url']	url
body']	body

テンプレートファイルの置換文字列の対応表(TAB区切り)

$this->Html->addCrumb	$this->Breadcrumbs->add
$this->Html->getCrumbs(' / ');	$this->Breadcrumbs->render(['class' => 'ib-breadcrumbs'], ['separator' => ' / ']);
FULL_BASE_URL	Router::fullBaseUrl()
$this->Form->input	$this->Form->control
$loginedUser['id']	$this->readAuthUser('id'
$loginedUser['role']	$this->readAuthUser('role'
$loginedUser['name']	$this->readAuthUser('name'
data[Content][kind]	kind
ContentBody	body
, 'class'=>'form-control']	]
kind']	kind
status']	status
created']	created
modified']	modified
id']	id
title']	title
name']	name
score']	score
sec']	sec
understanding']	understanding
password']	password

何度も繰り返し対応表を修正ができるように、以下のように、コンバート実行時にテキストボックスに張り付けるだけで、変更が可能としています。

CakePHP2 と CakePHP4 は別のフレームワークと言っていいぐらい破壊的な変更が行われているため、一発でコンバートできるような銀の弾丸はありません。しかしながら移行の方針を決め、ファイル名や文字列の単純な変更を自動化することで、スクラッチでリライトするよりもある程度工数を削減することが可能と思われます。またすぐに移行しなくても、移行を見据えて、既存のコードのリファクタリングを行うことは、将来、移行の必要性が発生した場合のリスクの軽減にもつながるものと思われます。

次回は認証周りの移行について書きたいと思います。

関連記事:

コメントを残す

メールアドレスが公開されることはありません。 が付いている欄は必須項目です

CAPTCHA


このサイトはスパムを低減するために Akismet を使っています。コメントデータの処理方法の詳細はこちらをご覧ください