Traitとは?
Laravelにおける「Trait(トレイト)」とは、再利用可能なメソッドの集まりを指すPHPの機能のこと。
Traitはクラスに直接インポートされ、そのクラスのメソッドを拡張するために使用される。
Traitは継承の制約を持たないため、複数のクラスで同じメソッドやプロパティを共有したい場合に有効。
Traitの利点
コードの再利用
一連のメソッドをTraitとしてまとめることで複数のクラスで同じコードを再利用でき、コードの重複を避けることができる。
機能の拡張
Traitを使用してクラスにメソッドを追加することで、そのクラスの機能を拡張できる。
例えばLaravelのTraitは、モデルに対して日付のフォーマットやソート機能を追加するために使用されることがある。
横断的な機能の提供
Traitは複数のクラスで使用されるため、Traitに含まれるメソッドは複数のクラスに対して共通の機能を提供できる。これによりアプリケーション全体で一貫性のある動作を実現可能。
継承(extends)と何が違うの?
階層構造の有無
継承はクラス間に階層構造を作る。親クラスから子クラスへのメソッドやプロパティの引き継がれる。
Traitは階層構造に依存せずにコードを再利用する。異なるクラスが異なるTraitを組み合わせての利用が可能。
継承の制約
継承は通常1つのクラスからのみしか継承できない。多重継承がある一部の言語ではクラスが複数の親クラスから継承することができるがその際に複雑性が生じる可能性がある。
Traitは複数のTraitを同じクラスに適用することができるためクラス間で異なるコードの組み合わせが実現できる。
コードの共有範囲
親クラスから子クラスへの継承はすべての子クラスで同じメソッドやプロパティが使用可能だがその階層内に限られる。
Traitは異なるクラス間でコードを共有できるため階層に依存せずに再利用できる。
柔軟性
継承は親クラスとの関係が固定されるため、クラスの構造や振る舞いを変更する際に柔軟性が制限されることがある。
Traitはクラス階層に縛られずにコードを再利用できるため、異なるクラスの組み合わせや変更に対して柔軟なアプローチが可能。
項目 | 継承(extends) | Trait |
---|---|---|
階層構造 | あり | なし |
継承の制約 | 1つの親クラス | 複数のTraitを同時に利用可能 |
コードの共有範囲 | 階層内で共有 | 異なるクラス間で共有 |
柔軟性 | 制限あり(固定の階層構造) | 高い柔軟性 |
メンバーの引き継ぎ | あり | なし |
コードの変更の影響範囲 | 子クラスのみに影響 | Traitを変更すると影響を受ける |
適している場面
・クラス間に明確な階層関係がない場合
・複数のクラス間で共通のコードを再利用したい場合
・多重継承を避けたい場合
・クラスの組み合わせを柔軟に変更したい場合
具体的
仮にモデルであるUserクラスに対して特定の機能を追加したい場合、Traitを使用してユーザー関連のロジックを共有することができる。
1. Traitの作成:
まず、Traitを定義する。とりあえずユーザーに関連するメソッドであるgetUserFullName
を提供するTraitを定義してみる。
// app/Traits/UserFunctionsTrait.php
namespace App\Traits;
trait UserFunctionsTrait
{
public function getUserFullName()
{
return $this->first_name . ' ' . $this->last_name;
}
}
2. モデルにTraitを適用
次に、User
クラス内でTrait をuseする。
// app/User.php
namespace App\Models;
use Illuminate\Database\Eloquent\Model;
use App\Traits\UserFunctionsTrait;
class User extends Model
{
use UserFunctionsTrait;
// モデルのその他の定義や関連付け
}
このコードで、User
クラスはUserFunctionsTrait
内で定義したメソッドを使用できるようになる。今回ではgetUserFullName
を利用することUser
クラスのメソッドのように使える。
3. Controller内で使用
コントローラー内でUser
モデルのTraitを使用する。
// app/Http/Controllers/UserController.php
namespace App\Http\Controllers;
use App\ModelsUser;
use Illuminate\Http\Request;
use App\Http\Controllers\Controller;
class UserController extends Controller
{
public function show($id)
{
$user = User::findOrFail($id);
$fullName = $user->getUserFullName();
return view('user.show', compact('user', 'fullName'));
}
}
今回ではshow
アクション内でUser
クラスのgetUserFullName`メソッドを使用して、ユーザーのフルネームを取得するようにしている。
TraitをModel内で使用することで共通のメソッドや機能を複数のモデルで再利用することが可能。
感想
継承するのはextends、共有するのはtrait、似ているようで用途が違うのでごっちゃしにないような注意しなければ。