時折、データベースのテーブルの役割が冗長になり一つにまとめる時があります。そういった時、それぞれ別のテーブルを指していたモデルクラスを統合した方がコードが整理されます。この記事では整理の楽な方法の一つを紹介します。
- クラス名を置換した場合、まとめて参照先のクラスの名前も置換される機能を持つIDE(例えばPhpStorm)がある
- 変更後、動作が壊れていないことを担保できるテストがある
- 統合されたテーブルは統合前のテーブルそれぞれの持っていたカラムと同じカラムを持つ
この記事では上記三点を前提とします。一つ目がなければ紹介する方法は使えません。二つ目は解説の省略目的がほとんどです。ない場合は何らかの方法で動作が壊れていないことを都度確認してください。三つ目はそういう状態でないとちょっと処理が尋常でなく大変だからです。あまりにも統合前後が違う場合、それは統合ではなく作り直しの領域になります。
まずテーブルが統合されるところから始めます。次のコードがある状態で hoge_members テーブルと fuga_members テーブルが members テーブルに統合されたとします。
class HogeMember extends Model
{
}
class FugaMember extends Model
{
}
暗黙の命名でテーブルにバインドされており、このバインド先がなくなります。そこでまず既存機能を壊さないためにバインドを直します。
class HogeMember extends Model
{
public $table = 'members';
}
class FugaMember extends Model
{
public $table = 'members';
}
それぞれのモデルクラスが members テーブルにバインドされました。同じテーブルを指すモデルクラスが複数合っても問題なく動作します。統合後のテーブルが統合前のテーブルを包含する様な場合、他に変更する必要のある点はありません。そのままのコードが使えます。しかしこの記事ではコードの整理が目的なので更にコードを変更します。
現在二つのモデルがあります。これを一つにまとめます。
class HogeMember extends Model
{
public $table = 'members';
}
class FugaMember extends Model
{
public $table = 'members';
}
まず行うのは内部に持つプロパティとメソッドの統合です。消さない方のモデルクラスに全定義を移動します。名前が被った別機能は適宜名前を置換したください。もしフレームワーク依存のメソッドであったりグローバルスコープが異なったりする場合、それは統合するべきモデルではありません。同じテーブルを指しますが別の役割を持つモデルです。
内部を合成した後は名前置換を行います。内部に持っていたものをまとめた方は変更後にあるべきクラス名に、もう片方は決して他と被らない様な名前に置換します。
class Member extends Model
{
public $table = 'members';
}
class FugaAAAAAAAAAAAMember extends Model
{
public $table = 'members';
}
そうしたら他と決して被らないようにした名前をソースコード全体から文字列置換します。
class Member extends Model
{
public $table = 'members';
}
class Member extends Model
{
public $table = 'members';
}
そして内部をまとめていない方の不要になったモデルクラスを削除します。
class Member extends Model
{
public $table = 'members';
}
前段階まででは大問題が一つ残っています。同名の名前の宣言があるとPHPはエラーを吐きます。これを文字列置換で消します。クラス削除直後次の様な文字列が色々な場所に残っているはずです。
use App\Models\Eloquents\Memberr;
use App\Models\Eloquents\Member;
この二重になっている部分を一重になる様に置換します。
use App\Models\Eloquents\User;
これで機能を壊さずクラスが減ってほぼ完成です。あとはPhpStormの"重複を見つける"や phpcpd でコピペ状態になっている重複コードを消すだけです。
sebastianbergmann/phpcpd: Copy/Paste Detector (CPD) for PHP code.