はじめに
1月から実務でPHP、Laravelを扱うことになり、キャッチアップに勤しんでおります。
Sanctumを使って認証機能を実装しようとした時にTraitという言葉が出てきて恥ずかしながら何のことかわかりませんでした笑
その時に軽く調べたことをメモとして残します!
きっかけ
php artisan install:api
コマンドでSanctumをインストールしたことが始まりでした。
INFO API scaffolding installed. Please add the [Laravel\Sanctum\HasApiTokens]
trait to your User model.
HasApiTokensというtraitをUserモデルに追加しろよというメッセージが出力されておりました。
Traitって何?
簡単にまとめます
-
Traitはモジュール的なもの
- クラスに再利用可能なコードを提供する仕組み
- 複数のクラス間で共有したい機能をまとめて定義したい時に使う
-
Trait内のメソッドがクラスで使えるようになる仕組み
-
use
キーワードでクラスにTraitを「組み込む」ことで、そのクラスの一部のように振る舞う - Trait内で定義されたメソッドやプロパティは、
use
したクラスのインスタンスからそのまま呼び出せる
-
クラスに部品を埋め込むようなイメージですね!
Traitの定義
trait HogeTrait {
Public function hoge() : void {
print 'hoge!!'
}
}
```php
### Traitの使用
```bash
class Foo
{
use HogeTrait;
public function callHoge()
{
$this->hoge();
}
}
上記のようにuseで指定することでそのクラスのインスタンスからtraitのhoge関数を呼び出せる
Traitの制約や特徴
-
定数は持つことができない誤った情報でした(失礼しました)- コメントにて教えていただけたのですがPHP8.2以降ではtraitが定数を持てるようになっているようです
- プロパティ、抽象/静的/インスタンスメソッドのみ使用可能
- クラスの継承、インターフェイスの実装はできない
- トレイとそのものをインスタンス化することはできない
- useはtraitブロックの中でも利用できるので、他のtraitを利用して別のtraitを実装することも可能
- Traitはカンマ区切りで複数指定することも可能 例:
use HogeTrait, FooTrait, PyoTrait;
- Traitは型を持たない、実装のみ提供
Traitの注意点
1.型は持たない
型を持つことができないので
interfaceとあわせて利用するのがお作法となるようですね。
Traitで定義されたメソッドを持つinterfaceを定義
Ihoge {
function hoge();
}
class Foo implements Ihoge {
use HogeTrait
}
こうすることで
- 型チェックが可能になる
LoggerInterface を使うことで、instanceof やメソッドの型引数で型の安全性を担保 - コードの再利用と型保証の両立
Traitで共通ロジックを提供しつつ、インターフェースで型を保証する設計にする - メソッドシグネチャの契約
インターフェースに記述したメソッドのシグネチャが統一され、予測可能なコードに
保守性や予測可能性をTraitを使用しつつも担保できるようになります。
2.名前衝突に注意する必要がある
クラス、トレイトと複数使用することで名前衝突が起きる可能性に留意しなければなりません。
名前が衝突した場合は下記の優先順位で動作します。
- 現在のクラスのメンバー
- トレイトのメンバー
- 親クラスのメンバー
トレイト同士で衝突したらエラーになります。
まとめ
簡単にですが以上になります。
Traitは抽象化クラスで表現することが難しい処理やプロパティを切り出したい時や複数のクラスで共有されるような処理やプロパティをまとめたい時に利用されることが多い機能のようですね。
今回の例では、HasApiTokens という Token生成に関わる処理やプロパティを持つTrait を User モデルに組み込むことで、認証に必要な機能を備えたUserモデルを簡単に実現するために利用している感じでした。
参考