Traitのすすめ

アイキャッチ画像

Trait(トレイト)って何?

phpで作成するClassから共通化出来る部分を分離したい場合どうするでしょうか?

まず一つ考えられるのは、共通処理を持った親Classを作成し、それを各子Classが継承することです。

ただ共通化したいパーツが複数あり、子Class側で好きなパーツを好きなように組み合わせたい場合はどうでしょうか?

phpが継承出来るClassは1つに制限されており親Classでは実現が出来ません。

そこで使用することになるのがTraitです。

Class定義の直後にuse hogehoge などと記載されているのがTraitです。

Laravel自体でも利用しているTrait

Modelの中で次のような記述を見たことはないでしょうか?

この場合、テスト用データ投入用のFactoryと論理削除に関する機能を追加しています。

このように継承とは別に追加したい共通した機能などを好きにトッピングできるのがTraitです。

どんな処理をTraitにするといいの?

複数のテーブルに対して同様の処理を行う場合に、更新処理を担うServiceにそれぞれ記述するのではなくTraitとして共通化することが考えられます。

具体的には、次のような処理が考えられます。

  • メニューやカテゴリに紐付く画像をアップロードして登録する処理
  • メニューやカテゴリのソート順を変更する処理
  • ログイン認証を行う処理(顧客のログインでも管理画面のログインでも内部的な処理は共通)

例えばソート順を変更する場合、各テーブルに共通したカラム sort_noを追加しておき、初期値としてのsort_noを自身のidとしておきます。

ソート順の変更は[ ↑ ][ ↓ ](上下矢印のボタン)およびページ内の行をドラッグして自由に変更するパターンの2種類ある場合、以下のようなTraitを作成することで共通化できます。

あとはメニューやカテゴリを更新するServiceに以下のように指定することで共通化が実現します。

ちなみに必須ではありませんが、Traitの名前としてXXXable(XXXが可能)という名前をつけることが多いです。

どこからも呼べるからと乱用しない

Traitはどこからでも呼び出すことができる強力な仕組みですが、階層の異なる複数の場所から呼び出すと、この謎のメソッドはどこで定義されているんだ?といった混乱を招きます。

共通化するというのは素敵なことですが、ServiceならServiceの階層専用のTraitとして共通化するのがおすすめです。

仮にシンプルな共通した関数を実現したい場合はTraitとして作成せずHelper関数として登録した方が良いでしょう。