Upgrade to Pro — share decks privately, control downloads, hide ads and more …

Laravel のメール認証の内部実装を掘り下げる - PHPerKaigi 2021

Laravel のメール認証の内部実装を掘り下げる - PHPerKaigi 2021

スライド内で紹介した設計方針で実装したサンプルコードも公開しています。
興味のある方はこちらも是非ご覧ください!

https://github.com/hamakou108/laravel-separate-user-sample

hamakou108

March 27, 2021
Tweet

More Decks by hamakou108

Other Decks in Programming

Transcript

  1. App User App\Models\User MustVerifyEmail を実装する = メール認証の有効化 ユーザー登録時に認証メールを送信する 認証 URL

    へのリクエストを検証する 認証⽇時を保存する ユーザー認証済みかどうかを検証する use Illuminate\Contracts\Auth\MustVerifyEmail; use Illuminate\Foundation\Auth\User as Authenticatable; class User extends Authenticatable implements MustVerifyEmail { use Notifiable; // ... } 1 2 3 4 5 6 7 8 9
  2. App User App\Models\User MustVerifyEmail を実装する = メール認証の有効化 ユーザー登録時に認証メールを送信する 認証 URL

    へのリクエストを検証する 認証⽇時を保存する ユーザー認証済みかどうかを検証する use Illuminate\Contracts\Auth\MustVerifyEmail; use Illuminate\Foundation\Auth\User as Authenticatable; class User extends Authenticatable implements MustVerifyEmail { use Notifiable; // ... } 1 2 3 4 5 6 7 8 9 class User extends Authenticatable implements MustVerifyEmail use Illuminate\Contracts\Auth\MustVerifyEmail; 1 use Illuminate\Foundation\Auth\User as Authenticatable; 2 3 4 { 5 use Notifiable; 6 7 // ... 8 } 9
  3. Starter kits (Laravel Breeze) を使うと さらに実装量が減る ├── app │ ├──

    Models │ ├── Http │ │ ├── Controllers │ │ └── Middleware │ └── Providers ├── routes ├── resources │ ├── css │ ├── js │ └── views ├── database │ └── migrations └── tests 1 2 3 4 5 6 7 8 9 10 11 12 13 14
  4. Starter kits (Laravel Breeze) を使うと さらに実装量が減る ├── app │ ├──

    Models │ ├── Http │ │ ├── Controllers │ │ └── Middleware │ └── Providers ├── routes ├── resources │ ├── css │ ├── js │ └── views ├── database │ └── migrations └── tests 1 2 3 4 5 6 7 8 9 10 11 12 13 14 ├── app │ ├── Models │ ├── Http │ │ ├── Controllers ├── routes ├── resources │ ├── css │ ├── js │ └── views └── tests 1 2 3 4 │ │ └── Middleware 5 │ └── Providers 6 7 8 9 10 11 ├── database 12 │ └── migrations 13 14
  5. Starter kits (Laravel Breeze) を使うと さらに実装量が減る ├── app │ ├──

    Models │ ├── Http │ │ ├── Controllers │ │ └── Middleware │ └── Providers ├── routes ├── resources │ ├── css │ ├── js │ └── views ├── database │ └── migrations └── tests 1 2 3 4 5 6 7 8 9 10 11 12 13 14 ├── app │ ├── Models │ ├── Http │ │ ├── Controllers ├── routes ├── resources │ ├── css │ ├── js │ └── views └── tests 1 2 3 4 │ │ └── Middleware 5 │ └── Providers 6 7 8 9 10 11 ├── database 12 │ └── migrations 13 14 ├── app │ ├── Models ├── routes 1 2 │ ├── Http 3 │ │ ├── Controllers 4 │ │ └── Middleware 5 │ └── Providers 6 7 ├── resources 8 │ ├── css 9 │ ├── js 10 │ └── views 11 ├── database 12 │ └── migrations 13 └── tests 14
  6. Starter kits (Laravel Breeze) を使うと さらに実装量が減る ├── app │ ├──

    Models <- MustVerifyEmail を実装するだけ ├── routes <- middleware('verified') を追加するだけ 1 2 │ ├── Http 3 │ │ ├── Controllers 4 │ │ └── Middleware 5 │ └── Providers 6 7 ├── resources 8 │ ├── css 9 │ ├── js 10 │ └── views 11 ├── database 12 │ └── migrations 13 └── tests 14
  7. App User (再掲) App\Models\User use Illuminate\Contracts\Auth\MustVerifyEmail; use Illuminate\Foundation\Auth\User as Authenticatable;

    class User extends Authenticatable implements MustVerifyEmail { use Notifiable; // ... } 1 2 3 4 5 6 7 8 9
  8. 依存先が⾒えるように書き直してみる Auth 関連の Contract とトレイト、 Eloquent Model 、 Notifiable に依存してい

    る use Illuminate\Auth\Authenticatable; use Illuminate\Auth\MustVerifyEmail; use Illuminate\Auth\Passwords\CanResetPassword; use Illuminate\Contracts\Auth\Access\Authorizable as AuthorizableContract; use Illuminate\Contracts\Auth\Authenticatable as AuthenticatableContract; use Illuminate\Contracts\Auth\CanResetPassword as CanResetPasswordContract; use Illuminate\Contracts\Auth\MustVerifyEmail as MustVerifyEmailContract; use Illuminate\Database\Eloquent\Model; use Illuminate\Foundation\Auth\Access\Authorizable; use Illuminate\Notifications\Notifiable; class User extends Model implements AuthenticatableContract, AuthorizableContract, CanResetPasswordContract, MustVerifyEmailContract { use Notifiable, Authenticatable 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19
  9. 依存先が⾒えるように書き直してみる Auth 関連の Contract とトレイト、 Eloquent Model 、 Notifiable に依存してい

    る use Illuminate\Auth\Authenticatable; use Illuminate\Auth\MustVerifyEmail; use Illuminate\Auth\Passwords\CanResetPassword; use Illuminate\Contracts\Auth\Access\Authorizable as AuthorizableContract; use Illuminate\Contracts\Auth\Authenticatable as AuthenticatableContract; use Illuminate\Contracts\Auth\CanResetPassword as CanResetPasswordContract; use Illuminate\Contracts\Auth\MustVerifyEmail as MustVerifyEmailContract; use Illuminate\Database\Eloquent\Model; use Illuminate\Foundation\Auth\Access\Authorizable; use Illuminate\Notifications\Notifiable; class User extends Model implements AuthenticatableContract, AuthorizableContract, CanResetPasswordContract, MustVerifyEmailContract { use Notifiable, Authenticatable 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 AuthenticatableContract, AuthorizableContract, CanResetPasswordContract, MustVerifyEmailContract Authenticatable, Authorizable, CanResetPassword, MustVerifyEmail; use Illuminate\Contracts\Auth\Authenticatable as AuthenticatableContract; 5 use Illuminate\Contracts\Auth\CanResetPassword as CanResetPasswordContract; 6 use Illuminate\Contracts\Auth\MustVerifyEmail as MustVerifyEmailContract; 7 use Illuminate\Database\Eloquent\Model; 8 use Illuminate\Foundation\Auth\Access\Authorizable; 9 use Illuminate\Notifications\Notifiable; 10 11 class User extends Model implements 12 13 14 15 16 { 17 use Notifiable, 18 19 20 21 22 } 23
  10. 依存先が⾒えるように書き直してみる Auth 関連の Contract とトレイト、 Eloquent Model 、 Notifiable に依存してい

    る use Illuminate\Auth\Authenticatable; use Illuminate\Auth\MustVerifyEmail; use Illuminate\Auth\Passwords\CanResetPassword; use Illuminate\Contracts\Auth\Access\Authorizable as AuthorizableContract; use Illuminate\Contracts\Auth\Authenticatable as AuthenticatableContract; use Illuminate\Contracts\Auth\CanResetPassword as CanResetPasswordContract; use Illuminate\Contracts\Auth\MustVerifyEmail as MustVerifyEmailContract; use Illuminate\Database\Eloquent\Model; use Illuminate\Foundation\Auth\Access\Authorizable; use Illuminate\Notifications\Notifiable; class User extends Model implements AuthenticatableContract, AuthorizableContract, CanResetPasswordContract, MustVerifyEmailContract { use Notifiable, Authenticatable 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 AuthenticatableContract, AuthorizableContract, CanResetPasswordContract, MustVerifyEmailContract Authenticatable use Illuminate\Auth\Authenticatable; 1 use Illuminate\Auth\MustVerifyEmail; 2 use Illuminate\Auth\Passwords\CanResetPassword; 3 use Illuminate\Contracts\Auth\Access\Authorizable as AuthorizableContract; 4 use Illuminate\Contracts\Auth\Authenticatable as AuthenticatableContract; 5 use Illuminate\Contracts\Auth\CanResetPassword as CanResetPasswordContract; 6 use Illuminate\Contracts\Auth\MustVerifyEmail as MustVerifyEmailContract; 7 use Illuminate\Database\Eloquent\Model; 8 use Illuminate\Foundation\Auth\Access\Authorizable; 9 use Illuminate\Notifications\Notifiable; 10 11 class User extends Model implements 12 13 14 15 16 { 17 use Notifiable, 18 19 use Illuminate\Database\Eloquent\Model; class User extends Model implements use Illuminate\Auth\Authenticatable; 1 use Illuminate\Auth\MustVerifyEmail; 2 use Illuminate\Auth\Passwords\CanResetPassword; 3 use Illuminate\Contracts\Auth\Access\Authorizable as AuthorizableContract; 4 use Illuminate\Contracts\Auth\Authenticatable as AuthenticatableContract; 5 use Illuminate\Contracts\Auth\CanResetPassword as CanResetPasswordContract; 6 use Illuminate\Contracts\Auth\MustVerifyEmail as MustVerifyEmailContract; 7 8 use Illuminate\Foundation\Auth\Access\Authorizable; 9 use Illuminate\Notifications\Notifiable; 10 11 12 AuthenticatableContract, 13 AuthorizableContract, 14 CanResetPasswordContract, 15 MustVerifyEmailContract 16 { 17 use Notifiable, 18 Authenticatable, 19
  11. 依存先が⾒えるように書き直してみる Auth 関連の Contract とトレイト、 Eloquent Model 、 Notifiable に依存してい

    る use Illuminate\Auth\Authenticatable; use Illuminate\Auth\MustVerifyEmail; use Illuminate\Auth\Passwords\CanResetPassword; use Illuminate\Contracts\Auth\Access\Authorizable as AuthorizableContract; use Illuminate\Contracts\Auth\Authenticatable as AuthenticatableContract; use Illuminate\Contracts\Auth\CanResetPassword as CanResetPasswordContract; use Illuminate\Contracts\Auth\MustVerifyEmail as MustVerifyEmailContract; use Illuminate\Database\Eloquent\Model; use Illuminate\Foundation\Auth\Access\Authorizable; use Illuminate\Notifications\Notifiable; class User extends Model implements AuthenticatableContract, AuthorizableContract, CanResetPasswordContract, MustVerifyEmailContract { use Notifiable, Authenticatable 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 AuthenticatableContract, AuthorizableContract, CanResetPasswordContract, MustVerifyEmailContract Authenticatable use Illuminate\Auth\Authenticatable; 1 use Illuminate\Auth\MustVerifyEmail; 2 use Illuminate\Auth\Passwords\CanResetPassword; 3 use Illuminate\Contracts\Auth\Access\Authorizable as AuthorizableContract; 4 use Illuminate\Contracts\Auth\Authenticatable as AuthenticatableContract; 5 use Illuminate\Contracts\Auth\CanResetPassword as CanResetPasswordContract; 6 use Illuminate\Contracts\Auth\MustVerifyEmail as MustVerifyEmailContract; 7 use Illuminate\Database\Eloquent\Model; 8 use Illuminate\Foundation\Auth\Access\Authorizable; 9 use Illuminate\Notifications\Notifiable; 10 11 class User extends Model implements 12 13 14 15 16 { 17 use Notifiable, 18 19 use Illuminate\Database\Eloquent\Model; class User extends Model implements use Illuminate\Auth\Authenticatable; 1 use Illuminate\Auth\MustVerifyEmail; 2 use Illuminate\Auth\Passwords\CanResetPassword; 3 use Illuminate\Contracts\Auth\Access\Authorizable as AuthorizableContract; 4 use Illuminate\Contracts\Auth\Authenticatable as AuthenticatableContract; 5 use Illuminate\Contracts\Auth\CanResetPassword as CanResetPasswordContract; 6 use Illuminate\Contracts\Auth\MustVerifyEmail as MustVerifyEmailContract; 7 8 use Illuminate\Foundation\Auth\Access\Authorizable; 9 use Illuminate\Notifications\Notifiable; 10 11 12 AuthenticatableContract, 13 AuthorizableContract, 14 CanResetPasswordContract, 15 MustVerifyEmailContract 16 { 17 use Notifiable, 18 Authenticatable 19 use Illuminate\Notifications\Notifiable; use Notifiable, use Illuminate\Contracts\Auth\Authenticatable as AuthenticatableContract; 5 use Illuminate\Contracts\Auth\CanResetPassword as CanResetPasswordContract; 6 use Illuminate\Contracts\Auth\MustVerifyEmail as MustVerifyEmailContract; 7 use Illuminate\Database\Eloquent\Model; 8 use Illuminate\Foundation\Auth\Access\Authorizable; 9 10 11 class User extends Model implements 12 AuthenticatableContract, 13 AuthorizableContract, 14 CanResetPasswordContract, 15 MustVerifyEmailContract 16 { 17 18 Authenticatable, 19 Authorizable, 20 CanResetPassword, 21 MustVerifyEmail; 22 } 23
  12. Auth 関連のトレイトの依存先 Illuminate\Auth\MustVerifyEmail Auth 関連の機能は App User を通して Eloquent と

    Notifiable に複雑に依存して いる trait MustVerifyEmail { /** * Mark the given user's email as verified. * * @return bool */ public function markEmailAsVerified() { return $this->forceFill([ 'email_verified_at' => $this->freshTimestamp(), ])->save(); } // ... /** * Send the email verification notification. * 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19
  13. Auth 関連のトレイトの依存先 Illuminate\Auth\MustVerifyEmail Auth 関連の機能は App User を通して Eloquent と

    Notifiable に複雑に依存して いる trait MustVerifyEmail { /** * Mark the given user's email as verified. * * @return bool */ public function markEmailAsVerified() { return $this->forceFill([ 'email_verified_at' => $this->freshTimestamp(), ])->save(); } // ... /** * Send the email verification notification. * 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 /** * Mark the given user's email as verified. * * @return bool */ public function markEmailAsVerified() { return $this->forceFill([ 'email_verified_at' => $this->freshTimestamp(), ])->save(); } trait MustVerifyEmail 1 { 2 3 4 5 6 7 8 9 10 11 12 13 14 // ... 15 16 /** 17 * Send the email verification notification. 18 * 19
  14. Auth 関連のトレイトの依存先 Illuminate\Auth\MustVerifyEmail Auth 関連の機能は App User を通して Eloquent と

    Notifiable に複雑に依存して いる trait MustVerifyEmail { /** * Mark the given user's email as verified. * * @return bool */ public function markEmailAsVerified() { return $this->forceFill([ 'email_verified_at' => $this->freshTimestamp(), ])->save(); } // ... /** * Send the email verification notification. * 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 /** * Mark the given user's email as verified. * * @return bool */ public function markEmailAsVerified() { return $this->forceFill([ 'email_verified_at' => $this->freshTimestamp(), ])->save(); } trait MustVerifyEmail 1 { 2 3 4 5 6 7 8 9 10 11 12 13 14 // ... 15 16 /** 17 * Send the email verification notification. 18 * 19 /** * Send the email verification notification. * * @return void */ public function sendEmailVerificationNotification() { $this->notify(new VerifyEmail); } return $this->forceFill([ 10 'email_verified_at' => $this->freshTimestamp(), 11 ])->save(); 12 } 13 14 // ... 15 16 17 18 19 20 21 22 23 24 25 26 // ... 27 } 28
  15. ⚠ この先、幾つかの User が出てきます 呼称 役割 App User 認証に⽤いる I/F

    を提供する Domain User ドメインのコアロジックを提供する Eloquent User User を永続化するための機能を提供する Notifiable User User に通知を送るための機能を提供する ※ 公式の呼称ではありません。
  16. Infra Repository Infra\Repository\Eloquent\UserRepository use Domain\User\UserRepository as UserRepositoryInterface; use Infra\Model\Eloquent\User as

    UserModel; class UserRepository implements UserRepositoryInterface { public function markEmailAsVerified(UserId $id): bool { return UserModel::where('id', $id->rawValue()) ->whereNull('email_verified_at') ->update([ 'email_verified_at' => Date::now(), ]); } // ... } 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16
  17. Infra Repository Infra\Repository\Eloquent\UserRepository use Domain\User\UserRepository as UserRepositoryInterface; use Infra\Model\Eloquent\User as

    UserModel; class UserRepository implements UserRepositoryInterface { public function markEmailAsVerified(UserId $id): bool { return UserModel::where('id', $id->rawValue()) ->whereNull('email_verified_at') ->update([ 'email_verified_at' => Date::now(), ]); } // ... } 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 class UserRepository implements UserRepositoryInterface use Domain\User\UserRepository as UserRepositoryInterface; 1 use Infra\Model\Eloquent\User as UserModel; 2 3 4 { 5 public function markEmailAsVerified(UserId $id): bool 6 { 7 return UserModel::where('id', $id->rawValue()) 8 ->whereNull('email_verified_at') 9 ->update([ 10 'email_verified_at' => Date::now(), 11 ]); 12 } 13 14 // ... 15 } 16
  18. Infra Repository Infra\Repository\Eloquent\UserRepository use Domain\User\UserRepository as UserRepositoryInterface; use Infra\Model\Eloquent\User as

    UserModel; class UserRepository implements UserRepositoryInterface { public function markEmailAsVerified(UserId $id): bool { return UserModel::where('id', $id->rawValue()) ->whereNull('email_verified_at') ->update([ 'email_verified_at' => Date::now(), ]); } // ... } 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 class UserRepository implements UserRepositoryInterface use Domain\User\UserRepository as UserRepositoryInterface; 1 use Infra\Model\Eloquent\User as UserModel; 2 3 4 { 5 public function markEmailAsVerified(UserId $id): bool 6 { 7 return UserModel::where('id', $id->rawValue()) 8 ->whereNull('email_verified_at') 9 ->update([ 10 'email_verified_at' => Date::now(), 11 ]); 12 } 13 14 // ... 15 } 16 public function markEmailAsVerified(UserId $id): bool { return UserModel::where('id', $id->rawValue()) ->whereNull('email_verified_at') ->update([ 'email_verified_at' => Date::now(), ]); } use Domain\User\UserRepository as UserRepositoryInterface; 1 use Infra\Model\Eloquent\User as UserModel; 2 3 class UserRepository implements UserRepositoryInterface 4 { 5 6 7 8 9 10 11 12 13 14 // ... 15 } 16
  19. RepositoryServiceProvider App\Providers\RepositoryServiceProvider インフラが変わる場合は Infra の UserRepository を差し替えれば良いだけにな った! use Domain\User\UserRepository;

    use Infra\Repository\Eloquent\UserRepository as EloquentUserRepository; class RepositoryServiceProvider extends ServiceProvider { public function register() { $this->app->bind( UserRepository::class, EloquentUserRepository::class ); } } 1 2 3 4 5 6 7 8 9 10 11 12 13
  20. RepositoryServiceProvider App\Providers\RepositoryServiceProvider インフラが変わる場合は Infra の UserRepository を差し替えれば良いだけにな った! use Domain\User\UserRepository;

    use Infra\Repository\Eloquent\UserRepository as EloquentUserRepository; class RepositoryServiceProvider extends ServiceProvider { public function register() { $this->app->bind( UserRepository::class, EloquentUserRepository::class ); } } 1 2 3 4 5 6 7 8 9 10 11 12 13 $this->app->bind( UserRepository::class, EloquentUserRepository::class ); use Domain\User\UserRepository; 1 use Infra\Repository\Eloquent\UserRepository as EloquentUserRepository; 2 3 class RepositoryServiceProvider extends ServiceProvider 4 { 5 public function register() 6 { 7 8 9 10 11 } 12 } 13
  21. Infra Notifier Infra\Notifier\Illuminate\UserNotifier use Domain\User\User; use Domain\User\UserNotifier as UserNotifierInterface; use

    Illuminate\Auth\Notifications\VerifyEmail; use Infra\Notifiable\User as NotifiableUser; use Infra\Notifications\VerifyEmail; class UserNotifier implements UserNotifierInterface { private Dispatcher $dispatcher; public function __construct(Dispatcher $dispatcher) { $this->dispatcher = $dispatcher; } public function sendEmailVerificationNotification( User $user, string $url ): void { $this >dispatcher >send( 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19
  22. Infra Notifier Infra\Notifier\Illuminate\UserNotifier use Domain\User\User; use Domain\User\UserNotifier as UserNotifierInterface; use

    Illuminate\Auth\Notifications\VerifyEmail; use Infra\Notifiable\User as NotifiableUser; use Infra\Notifications\VerifyEmail; class UserNotifier implements UserNotifierInterface { private Dispatcher $dispatcher; public function __construct(Dispatcher $dispatcher) { $this->dispatcher = $dispatcher; } public function sendEmailVerificationNotification( User $user, string $url ): void { $this >dispatcher >send( 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 class UserNotifier implements UserNotifierInterface use Domain\User\User; 1 use Domain\User\UserNotifier as UserNotifierInterface; 2 use Illuminate\Auth\Notifications\VerifyEmail; 3 use Infra\Notifiable\User as NotifiableUser; 4 use Infra\Notifications\VerifyEmail; 5 6 7 { 8 private Dispatcher $dispatcher; 9 10 public function __construct(Dispatcher $dispatcher) { 11 $this->dispatcher = $dispatcher; 12 } 13 14 public function sendEmailVerificationNotification( 15 User $user, 16 string $url 17 ): void { 18 $this >dispatcher >send( 19
  23. Infra Notifier Infra\Notifier\Illuminate\UserNotifier use Domain\User\User; use Domain\User\UserNotifier as UserNotifierInterface; use

    Illuminate\Auth\Notifications\VerifyEmail; use Infra\Notifiable\User as NotifiableUser; use Infra\Notifications\VerifyEmail; class UserNotifier implements UserNotifierInterface { private Dispatcher $dispatcher; public function __construct(Dispatcher $dispatcher) { $this->dispatcher = $dispatcher; } public function sendEmailVerificationNotification( User $user, string $url ): void { $this >dispatcher >send( 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 class UserNotifier implements UserNotifierInterface use Domain\User\User; 1 use Domain\User\UserNotifier as UserNotifierInterface; 2 use Illuminate\Auth\Notifications\VerifyEmail; 3 use Infra\Notifiable\User as NotifiableUser; 4 use Infra\Notifications\VerifyEmail; 5 6 7 { 8 private Dispatcher $dispatcher; 9 10 public function __construct(Dispatcher $dispatcher) { 11 $this->dispatcher = $dispatcher; 12 } 13 14 public function sendEmailVerificationNotification( 15 User $user, 16 string $url 17 ): void { 18 $this >dispatcher >send( 19 public function __construct(Dispatcher $dispatcher) { $this->dispatcher = $dispatcher; } use Illuminate\Auth\Notifications\VerifyEmail; 3 use Infra\Notifiable\User as NotifiableUser; 4 use Infra\Notifications\VerifyEmail; 5 6 class UserNotifier implements UserNotifierInterface 7 { 8 private Dispatcher $dispatcher; 9 10 11 12 13 14 public function sendEmailVerificationNotification( 15 User $user, 16 string $url 17 ): void { 18 $this->dispatcher->send( 19 new NotifiableUser($user), 20 new VerifyEmail($url) 21
  24. Infra Notifier Infra\Notifier\Illuminate\UserNotifier use Domain\User\User; use Domain\User\UserNotifier as UserNotifierInterface; use

    Illuminate\Auth\Notifications\VerifyEmail; use Infra\Notifiable\User as NotifiableUser; use Infra\Notifications\VerifyEmail; class UserNotifier implements UserNotifierInterface { private Dispatcher $dispatcher; public function __construct(Dispatcher $dispatcher) { $this->dispatcher = $dispatcher; } public function sendEmailVerificationNotification( User $user, string $url ): void { $this >dispatcher >send( 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 class UserNotifier implements UserNotifierInterface use Domain\User\User; 1 use Domain\User\UserNotifier as UserNotifierInterface; 2 use Illuminate\Auth\Notifications\VerifyEmail; 3 use Infra\Notifiable\User as NotifiableUser; 4 use Infra\Notifications\VerifyEmail; 5 6 7 { 8 private Dispatcher $dispatcher; 9 10 public function __construct(Dispatcher $dispatcher) { 11 $this->dispatcher = $dispatcher; 12 } 13 14 public function sendEmailVerificationNotification( 15 User $user, 16 string $url 17 ): void { 18 $this >dispatcher >send( 19 public function __construct(Dispatcher $dispatcher) { $this->dispatcher = $dispatcher; } use Domain\User\User; 1 use Domain\User\UserNotifier as UserNotifierInterface; 2 use Illuminate\Auth\Notifications\VerifyEmail; 3 use Infra\Notifiable\User as NotifiableUser; 4 use Infra\Notifications\VerifyEmail; 5 6 class UserNotifier implements UserNotifierInterface 7 { 8 private Dispatcher $dispatcher; 9 10 11 12 13 14 public function sendEmailVerificationNotification( 15 User $user, 16 string $url 17 ): void { 18 $this >dispatcher >send( 19 public function sendEmailVerificationNotification( User $user, string $url ): void { $this->dispatcher->send( new NotifiableUser($user), new VerifyEmail($url) ); } 6 class UserNotifier implements UserNotifierInterface 7 { 8 private Dispatcher $dispatcher; 9 10 public function __construct(Dispatcher $dispatcher) { 11 $this->dispatcher = $dispatcher; 12 } 13 14 15 16 17 18 19 20 21 22 23 } 24
  25. Notifiable Infra\Notifiable\User use Domain\User\User as DomainUser; use Illuminate\Notifications\Notifiable; class User

    { use Notifiable; private DomainUser $user; public function __construct(DomainUser $user) { $this->user = $user; } public function routeNotificationForMail() { return $this->user->getRawEmail(); } } 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19
  26. Notifiable Infra\Notifiable\User use Domain\User\User as DomainUser; use Illuminate\Notifications\Notifiable; class User

    { use Notifiable; private DomainUser $user; public function __construct(DomainUser $user) { $this->user = $user; } public function routeNotificationForMail() { return $this->user->getRawEmail(); } } 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 use Notifiable; use Domain\User\User as DomainUser; 1 use Illuminate\Notifications\Notifiable; 2 3 class User 4 { 5 6 7 private DomainUser $user; 8 9 public function __construct(DomainUser $user) 10 { 11 $this->user = $user; 12 } 13 14 public function routeNotificationForMail() 15 { 16 return $this->user->getRawEmail(); 17 } 18 } 19
  27. Notification Infra\Notifications\VerifyEmail use Illuminate\Auth\Notifications\VerifyEmail as IlluminateVerifyEmail; class VerifyEmail extends IlluminateVerifyEmail

    { private string $verificationUrl; public function __construct(string $verificationUrl) { $this->verificationUrl = $verificationUrl; } /** * @inheritDoc */ public function toMail($notifiable) { return $this->buildMailMessage($this->verificationUrl); } } 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19
  28. Notification Infra\Notifications\VerifyEmail use Illuminate\Auth\Notifications\VerifyEmail as IlluminateVerifyEmail; class VerifyEmail extends IlluminateVerifyEmail

    { private string $verificationUrl; public function __construct(string $verificationUrl) { $this->verificationUrl = $verificationUrl; } /** * @inheritDoc */ public function toMail($notifiable) { return $this->buildMailMessage($this->verificationUrl); } } 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 class VerifyEmail extends IlluminateVerifyEmail use Illuminate\Auth\Notifications\VerifyEmail as IlluminateVerifyEmail; 1 2 3 { 4 private string $verificationUrl; 5 6 public function __construct(string $verificationUrl) 7 { 8 $this->verificationUrl = $verificationUrl; 9 } 10 11 /** 12 * @inheritDoc 13 */ 14 public function toMail($notifiable) 15 { 16 return $this->buildMailMessage($this->verificationUrl); 17 } 18 } 19
  29. Notification Infra\Notifications\VerifyEmail use Illuminate\Auth\Notifications\VerifyEmail as IlluminateVerifyEmail; class VerifyEmail extends IlluminateVerifyEmail

    { private string $verificationUrl; public function __construct(string $verificationUrl) { $this->verificationUrl = $verificationUrl; } /** * @inheritDoc */ public function toMail($notifiable) { return $this->buildMailMessage($this->verificationUrl); } } 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 class VerifyEmail extends IlluminateVerifyEmail use Illuminate\Auth\Notifications\VerifyEmail as IlluminateVerifyEmail; 1 2 3 { 4 private string $verificationUrl; 5 6 public function __construct(string $verificationUrl) 7 { 8 $this->verificationUrl = $verificationUrl; 9 } 10 11 /** 12 * @inheritDoc 13 */ 14 public function toMail($notifiable) 15 { 16 return $this->buildMailMessage($this->verificationUrl); 17 } 18 } 19 private string $verificationUrl; public function __construct(string $verificationUrl) { $this->verificationUrl = $verificationUrl; } use Illuminate\Auth\Notifications\VerifyEmail as IlluminateVerifyEmail; 1 2 class VerifyEmail extends IlluminateVerifyEmail 3 { 4 5 6 7 8 9 10 11 /** 12 * @inheritDoc 13 */ 14 public function toMail($notifiable) 15 { 16 return $this->buildMailMessage($this->verificationUrl); 17 } 18 } 19
  30. Notification Infra\Notifications\VerifyEmail use Illuminate\Auth\Notifications\VerifyEmail as IlluminateVerifyEmail; class VerifyEmail extends IlluminateVerifyEmail

    { private string $verificationUrl; public function __construct(string $verificationUrl) { $this->verificationUrl = $verificationUrl; } /** * @inheritDoc */ public function toMail($notifiable) { return $this->buildMailMessage($this->verificationUrl); } } 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 class VerifyEmail extends IlluminateVerifyEmail use Illuminate\Auth\Notifications\VerifyEmail as IlluminateVerifyEmail; 1 2 3 { 4 private string $verificationUrl; 5 6 public function __construct(string $verificationUrl) 7 { 8 $this->verificationUrl = $verificationUrl; 9 } 10 11 /** 12 * @inheritDoc 13 */ 14 public function toMail($notifiable) 15 { 16 return $this->buildMailMessage($this->verificationUrl); 17 } 18 } 19 private string $verificationUrl; public function __construct(string $verificationUrl) { $this->verificationUrl = $verificationUrl; } use Illuminate\Auth\Notifications\VerifyEmail as IlluminateVerifyEmail; 1 2 class VerifyEmail extends IlluminateVerifyEmail 3 { 4 5 6 7 8 9 10 11 /** 12 * @inheritDoc 13 */ 14 public function toMail($notifiable) 15 { 16 return $this->buildMailMessage($this->verificationUrl); 17 } 18 } 19 /** * @inheritDoc */ public function toMail($notifiable) { return $this->buildMailMessage($this->verificationUrl); } use Illuminate\Auth\Notifications\VerifyEmail as IlluminateVerifyEmail; 1 2 class VerifyEmail extends IlluminateVerifyEmail 3 { 4 private string $verificationUrl; 5 6 public function __construct(string $verificationUrl) 7 { 8 $this->verificationUrl = $verificationUrl; 9 } 10 11 12 13 14 15 16 17 18 } 19
  31. 認証 URL の⽣成処理はどこ? Illuminate\Auth\Notifications\VerifyEmail getKey は Eloquent Model のメソッドなので使えない! 認証

    URL の⽣成を Notification から App User に切り出そう use Illuminate\Notifications\Notification; class VerifyEmail extends Notification { // ... /** * Build the mail representation of the notification. * * @param mixed $notifiable * @return \Illuminate\Notifications\Messages\MailMessage */ public function toMail($notifiable) { $verificationUrl = $this->verificationUrl($notifiable); if (static::$toMailCallback) { return call_user_func(static::$toMailCallback, $notifiable, $verificationUrl); } 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19
  32. 認証 URL の⽣成処理はどこ? Illuminate\Auth\Notifications\VerifyEmail getKey は Eloquent Model のメソッドなので使えない! 認証

    URL の⽣成を Notification から App User に切り出そう use Illuminate\Notifications\Notification; class VerifyEmail extends Notification { // ... /** * Build the mail representation of the notification. * * @param mixed $notifiable * @return \Illuminate\Notifications\Messages\MailMessage */ public function toMail($notifiable) { $verificationUrl = $this->verificationUrl($notifiable); if (static::$toMailCallback) { return call_user_func(static::$toMailCallback, $notifiable, $verificationUrl); } 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 /** * Build the mail representation of the notification. * * @param mixed $notifiable * @return \Illuminate\Notifications\Messages\MailMessage */ public function toMail($notifiable) { $verificationUrl = $this->verificationUrl($notifiable); if (static::$toMailCallback) { return call_user_func(static::$toMailCallback, $notifiable, $verificationUrl); } return $this->buildMailMessage($verificationUrl); } // ... 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 // 24
  33. 認証 URL の⽣成処理はどこ? Illuminate\Auth\Notifications\VerifyEmail getKey は Eloquent Model のメソッドなので使えない! 認証

    URL の⽣成を Notification から App User に切り出そう use Illuminate\Notifications\Notification; class VerifyEmail extends Notification { // ... /** * Build the mail representation of the notification. * * @param mixed $notifiable * @return \Illuminate\Notifications\Messages\MailMessage */ public function toMail($notifiable) { $verificationUrl = $this->verificationUrl($notifiable); if (static::$toMailCallback) { return call_user_func(static::$toMailCallback, $notifiable, $verificationUrl); } 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 /** * Build the mail representation of the notification. * * @param mixed $notifiable * @return \Illuminate\Notifications\Messages\MailMessage */ public function toMail($notifiable) { $verificationUrl = $this->verificationUrl($notifiable); if (static::$toMailCallback) { return call_user_func(static::$toMailCallback, $notifiable, $verificationUrl); } use Illuminate\Notifications\Notification; 1 2 class VerifyEmail extends Notification 3 { 4 // ... 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 $verificationUrl = $this->verificationUrl($notifiable); 6 /** 7 * Build the mail representation of the notification. 8 * 9 * @param mixed $notifiable 10 * @return \Illuminate\Notifications\Messages\MailMessage 11 */ 12 public function toMail($notifiable) 13 { 14 15 16 if (static::$toMailCallback) { 17 return call_user_func(static::$toMailCallback, $notifiable, $verificationUrl); 18 } 19 20 return $this->buildMailMessage($verificationUrl); 21 } 22 23 // ... 24
  34. 認証 URL の⽣成処理はどこ? Illuminate\Auth\Notifications\VerifyEmail getKey は Eloquent Model のメソッドなので使えない! 認証

    URL の⽣成を Notification から App User に切り出そう use Illuminate\Notifications\Notification; class VerifyEmail extends Notification { // ... /** * Build the mail representation of the notification. * * @param mixed $notifiable * @return \Illuminate\Notifications\Messages\MailMessage */ public function toMail($notifiable) { $verificationUrl = $this->verificationUrl($notifiable); if (static::$toMailCallback) { return call_user_func(static::$toMailCallback, $notifiable, $verificationUrl); } 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 /** * Build the mail representation of the notification. * * @param mixed $notifiable * @return \Illuminate\Notifications\Messages\MailMessage */ public function toMail($notifiable) { $verificationUrl = $this->verificationUrl($notifiable); if (static::$toMailCallback) { return call_user_func(static::$toMailCallback, $notifiable, $verificationUrl); } use Illuminate\Notifications\Notification; 1 2 class VerifyEmail extends Notification 3 { 4 // ... 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 $verificationUrl = $this->verificationUrl($notifiable); use Illuminate\Notifications\Notification; 1 2 class VerifyEmail extends Notification 3 { 4 // ... 5 6 /** 7 * Build the mail representation of the notification. 8 * 9 * @param mixed $notifiable 10 * @return \Illuminate\Notifications\Messages\MailMessage 11 */ 12 public function toMail($notifiable) 13 { 14 15 16 if (static::$toMailCallback) { 17 return call_user_func(static::$toMailCallback, $notifiable, $verificationUrl); 18 } 19 // ... /** * Get the verification URL for the given notifiable. * * @param mixed $notifiable * @return string */ protected function verificationUrl($notifiable) { if (static::$createUrlCallback) { return call_user_func(static::$createUrlCallback, $notifiable); } return URL::temporarySignedRoute( 'verification.verify', Carbon::now()->addMinutes(Config::get('auth.verification.expire', 60)), [ 'id' $ tifi bl t () 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42
  35. 認証 URL の⽣成処理はどこ? Illuminate\Auth\Notifications\VerifyEmail getKey は Eloquent Model のメソッドなので使えない! 認証

    URL の⽣成を Notification から App User に切り出そう use Illuminate\Notifications\Notification; class VerifyEmail extends Notification { // ... /** * Build the mail representation of the notification. * * @param mixed $notifiable * @return \Illuminate\Notifications\Messages\MailMessage */ public function toMail($notifiable) { $verificationUrl = $this->verificationUrl($notifiable); if (static::$toMailCallback) { return call_user_func(static::$toMailCallback, $notifiable, $verificationUrl); } 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 /** * Build the mail representation of the notification. * * @param mixed $notifiable * @return \Illuminate\Notifications\Messages\MailMessage */ public function toMail($notifiable) { $verificationUrl = $this->verificationUrl($notifiable); if (static::$toMailCallback) { return call_user_func(static::$toMailCallback, $notifiable, $verificationUrl); } use Illuminate\Notifications\Notification; 1 2 class VerifyEmail extends Notification 3 { 4 // ... 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 $verificationUrl = $this->verificationUrl($notifiable); use Illuminate\Notifications\Notification; 1 2 class VerifyEmail extends Notification 3 { 4 // ... 5 6 /** 7 * Build the mail representation of the notification. 8 * 9 * @param mixed $notifiable 10 * @return \Illuminate\Notifications\Messages\MailMessage 11 */ 12 public function toMail($notifiable) 13 { 14 15 16 if (static::$toMailCallback) { 17 return call_user_func(static::$toMailCallback, $notifiable, $verificationUrl); 18 } 19 use Illuminate\Notifications\Notification; 1 2 class VerifyEmail extends Notification 3 { 4 // ... 5 6 /** 7 * Build the mail representation of the notification. 8 * 9 * @param mixed $notifiable 10 * @return \Illuminate\Notifications\Messages\MailMessage 11 */ 12 public function toMail($notifiable) 13 { 14 $verificationUrl = $this->verificationUrl($notifiable); 15 16 if (static::$toMailCallback) { 17 return call_user_func(static::$toMailCallback, $notifiable, $verificationUrl); 18 } 19 return URL::temporarySignedRoute( 'verification.verify', Carbon::now()->addMinutes(Config::get('auth.verification.expire', 60)), [ 'id' => $notifiable->getKey(), 'hash' => sha1($notifiable->getEmailForVerification()), ] ); */ 31 protected function verificationUrl($notifiable) 32 { 33 if (static::$createUrlCallback) { 34 return call_user_func(static::$createUrlCallback, $notifiable); 35 } 36 37 38 39 40 41 42 43 44 45 } 46 47 // ... 48 } 49
  36. 認証 URL の⽣成処理はどこ? Illuminate\Auth\Notifications\VerifyEmail getKey は Eloquent Model のメソッドなので使えない! 認証

    URL の⽣成を Notification から App User に切り出そう use Illuminate\Notifications\Notification; class VerifyEmail extends Notification { // ... /** * Build the mail representation of the notification. * * @param mixed $notifiable * @return \Illuminate\Notifications\Messages\MailMessage */ public function toMail($notifiable) { $verificationUrl = $this->verificationUrl($notifiable); if (static::$toMailCallback) { return call_user_func(static::$toMailCallback, $notifiable, $verificationUrl); } 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 /** * Build the mail representation of the notification. * * @param mixed $notifiable * @return \Illuminate\Notifications\Messages\MailMessage */ public function toMail($notifiable) { $verificationUrl = $this->verificationUrl($notifiable); if (static::$toMailCallback) { return call_user_func(static::$toMailCallback, $notifiable, $verificationUrl); } use Illuminate\Notifications\Notification; 1 2 class VerifyEmail extends Notification 3 { 4 // ... 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 $verificationUrl = $this->verificationUrl($notifiable); use Illuminate\Notifications\Notification; 1 2 class VerifyEmail extends Notification 3 { 4 // ... 5 6 /** 7 * Build the mail representation of the notification. 8 * 9 * @param mixed $notifiable 10 * @return \Illuminate\Notifications\Messages\MailMessage 11 */ 12 public function toMail($notifiable) 13 { 14 15 16 if (static::$toMailCallback) { 17 return call_user_func(static::$toMailCallback, $notifiable, $verificationUrl); 18 } 19 use Illuminate\Notifications\Notification; 1 2 class VerifyEmail extends Notification 3 { 4 // ... 5 6 /** 7 * Build the mail representation of the notification. 8 * 9 * @param mixed $notifiable 10 * @return \Illuminate\Notifications\Messages\MailMessage 11 */ 12 public function toMail($notifiable) 13 { 14 $verificationUrl = $this->verificationUrl($notifiable); 15 16 if (static::$toMailCallback) { 17 return call_user_func(static::$toMailCallback, $notifiable, $verificationUrl); 18 } 19 use Illuminate\Notifications\Notification; 1 2 class VerifyEmail extends Notification 3 { 4 // ... 5 6 /** 7 * Build the mail representation of the notification. 8 * 9 * @param mixed $notifiable 10 * @return \Illuminate\Notifications\Messages\MailMessage 11 */ 12 public function toMail($notifiable) 13 { 14 $verificationUrl = $this->verificationUrl($notifiable); 15 16 if (static::$toMailCallback) { 17 return call_user_func(static::$toMailCallback, $notifiable, $verificationUrl); 18 } 19 [ 'id' => $notifiable->getKey(), 'hash' => sha1($notifiable->getEmailForVerification()), ] */ 31 protected function verificationUrl($notifiable) 32 { 33 if (static::$createUrlCallback) { 34 return call_user_func(static::$createUrlCallback, $notifiable); 35 } 36 37 return URL::temporarySignedRoute( 38 'verification.verify', 39 Carbon::now()->addMinutes(Config::get('auth.verification.expire', 60)), 40 41 42 43 44 ); 45 } 46 47 // ... 48 } 49
  37. 認証 URL の⽣成処理はどこ? Illuminate\Auth\Notifications\VerifyEmail getKey は Eloquent Model のメソッドなので使えない! 認証

    URL の⽣成を Notification から App User に切り出そう use Illuminate\Notifications\Notification; class VerifyEmail extends Notification { // ... /** * Build the mail representation of the notification. * * @param mixed $notifiable * @return \Illuminate\Notifications\Messages\MailMessage */ public function toMail($notifiable) { $verificationUrl = $this->verificationUrl($notifiable); if (static::$toMailCallback) { return call_user_func(static::$toMailCallback, $notifiable, $verificationUrl); } 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 /** * Build the mail representation of the notification. * * @param mixed $notifiable * @return \Illuminate\Notifications\Messages\MailMessage */ public function toMail($notifiable) { $verificationUrl = $this->verificationUrl($notifiable); if (static::$toMailCallback) { return call_user_func(static::$toMailCallback, $notifiable, $verificationUrl); } use Illuminate\Notifications\Notification; 1 2 class VerifyEmail extends Notification 3 { 4 // ... 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 $verificationUrl = $this->verificationUrl($notifiable); use Illuminate\Notifications\Notification; 1 2 class VerifyEmail extends Notification 3 { 4 // ... 5 6 /** 7 * Build the mail representation of the notification. 8 * 9 * @param mixed $notifiable 10 * @return \Illuminate\Notifications\Messages\MailMessage 11 */ 12 public function toMail($notifiable) 13 { 14 15 16 if (static::$toMailCallback) { 17 return call_user_func(static::$toMailCallback, $notifiable, $verificationUrl); 18 } 19 use Illuminate\Notifications\Notification; 1 2 class VerifyEmail extends Notification 3 { 4 // ... 5 6 /** 7 * Build the mail representation of the notification. 8 * 9 * @param mixed $notifiable 10 * @return \Illuminate\Notifications\Messages\MailMessage 11 */ 12 public function toMail($notifiable) 13 { 14 $verificationUrl = $this->verificationUrl($notifiable); 15 16 if (static::$toMailCallback) { 17 return call_user_func(static::$toMailCallback, $notifiable, $verificationUrl); 18 } 19 use Illuminate\Notifications\Notification; 1 2 class VerifyEmail extends Notification 3 { 4 // ... 5 6 /** 7 * Build the mail representation of the notification. 8 * 9 * @param mixed $notifiable 10 * @return \Illuminate\Notifications\Messages\MailMessage 11 */ 12 public function toMail($notifiable) 13 { 14 $verificationUrl = $this->verificationUrl($notifiable); 15 16 if (static::$toMailCallback) { 17 return call_user_func(static::$toMailCallback, $notifiable, $verificationUrl); 18 } 19 use Illuminate\Notifications\Notification; 1 2 class VerifyEmail extends Notification 3 { 4 // ... 5 6 /** 7 * Build the mail representation of the notification. 8 * 9 * @param mixed $notifiable 10 * @return \Illuminate\Notifications\Messages\MailMessage 11 */ 12 public function toMail($notifiable) 13 { 14 $verificationUrl = $this->verificationUrl($notifiable); 15 16 if (static::$toMailCallback) { 17 return call_user_func(static::$toMailCallback, $notifiable, $verificationUrl); 18 } 19 'id' => $notifiable->getKey(), */ 31 protected function verificationUrl($notifiable) 32 { 33 if (static::$createUrlCallback) { 34 return call_user_func(static::$createUrlCallback, $notifiable); 35 } 36 37 return URL::temporarySignedRoute( 38 'verification.verify', 39 Carbon::now()->addMinutes(Config::get('auth.verification.expire', 60)), 40 [ 41 42 'hash' => sha1($notifiable->getEmailForVerification()), 43 ] 44 ); 45 } 46 47 // ... 48 } 49
  38. App User App\Models\User Eloquent Model と Notifiable への依存がなくなった! Respository と

    Notifier のインターフェースにのみ依存 use Domain\User\UserId; use Domain\User\UserNotifier; use Domain\User\UserRepository; use Illuminate\Contracts\Auth\Access\Authorizable as AuthorizableContract; use Illuminate\Contracts\Auth\Authenticatable as AuthenticatableContract; use Illuminate\Contracts\Auth\CanResetPassword as CanResetPasswordContract; use Illuminate\Contracts\Auth\MustVerifyEmail as MustVerifyEmailContract; use Illuminate\Foundation\Auth\Access\Authorizable; class User implements AuthenticatableContract, AuthorizableContract, CanResetPasswordContract, MustVerifyEmailContract { use Authorizable; private UserId $id; private UserRepository $repository; 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19
  39. App User App\Models\User Eloquent Model と Notifiable への依存がなくなった! Respository と

    Notifier のインターフェースにのみ依存 use Domain\User\UserId; use Domain\User\UserNotifier; use Domain\User\UserRepository; use Illuminate\Contracts\Auth\Access\Authorizable as AuthorizableContract; use Illuminate\Contracts\Auth\Authenticatable as AuthenticatableContract; use Illuminate\Contracts\Auth\CanResetPassword as CanResetPasswordContract; use Illuminate\Contracts\Auth\MustVerifyEmail as MustVerifyEmailContract; use Illuminate\Foundation\Auth\Access\Authorizable; class User implements AuthenticatableContract, AuthorizableContract, CanResetPasswordContract, MustVerifyEmailContract { use Authorizable; private UserId $id; private UserRepository $repository; 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 class User implements AuthenticatableContract, AuthorizableContract, CanResetPasswordContract, MustVerifyEmailContract use Domain\User\UserRepository; 3 use Illuminate\Contracts\Auth\Access\Authorizable as AuthorizableContract; 4 use Illuminate\Contracts\Auth\Authenticatable as AuthenticatableContract; 5 use Illuminate\Contracts\Auth\CanResetPassword as CanResetPasswordContract; 6 use Illuminate\Contracts\Auth\MustVerifyEmail as MustVerifyEmailContract; 7 use Illuminate\Foundation\Auth\Access\Authorizable; 8 9 10 11 12 13 14 { 15 use Authorizable; 16 17 private UserId $id; 18 private UserRepository $repository; 19 private UserNotifier $notifier; 20 21
  40. App User App\Models\User Eloquent Model と Notifiable への依存がなくなった! Respository と

    Notifier のインターフェースにのみ依存 use Domain\User\UserId; use Domain\User\UserNotifier; use Domain\User\UserRepository; use Illuminate\Contracts\Auth\Access\Authorizable as AuthorizableContract; use Illuminate\Contracts\Auth\Authenticatable as AuthenticatableContract; use Illuminate\Contracts\Auth\CanResetPassword as CanResetPasswordContract; use Illuminate\Contracts\Auth\MustVerifyEmail as MustVerifyEmailContract; use Illuminate\Foundation\Auth\Access\Authorizable; class User implements AuthenticatableContract, AuthorizableContract, CanResetPasswordContract, MustVerifyEmailContract { use Authorizable; private UserId $id; private UserRepository $repository; 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 class User implements AuthenticatableContract, AuthorizableContract, CanResetPasswordContract, MustVerifyEmailContract use Domain\User\UserId; 1 use Domain\User\UserNotifier; 2 use Domain\User\UserRepository; 3 use Illuminate\Contracts\Auth\Access\Authorizable as AuthorizableContract; 4 use Illuminate\Contracts\Auth\Authenticatable as AuthenticatableContract; 5 use Illuminate\Contracts\Auth\CanResetPassword as CanResetPasswordContract; 6 use Illuminate\Contracts\Auth\MustVerifyEmail as MustVerifyEmailContract; 7 use Illuminate\Foundation\Auth\Access\Authorizable; 8 9 10 11 12 13 14 { 15 use Authorizable; 16 17 private UserId $id; 18 private UserRepository $repository; 19 private UserId $id; private UserRepository $repository; private UserNotifier $notifier; public function __construct( UserId $id, UserRepository $repository, UserNotifier $notifier ) { $this->id = $id; $this->repository = $repository; $this->notifier = $notifier; } { 15 use Authorizable; 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 // ... 32 33
  41. App User App\Models\User Eloquent Model と Notifiable への依存がなくなった! Respository と

    Notifier のインターフェースにのみ依存 use Domain\User\UserId; use Domain\User\UserNotifier; use Domain\User\UserRepository; use Illuminate\Contracts\Auth\Access\Authorizable as AuthorizableContract; use Illuminate\Contracts\Auth\Authenticatable as AuthenticatableContract; use Illuminate\Contracts\Auth\CanResetPassword as CanResetPasswordContract; use Illuminate\Contracts\Auth\MustVerifyEmail as MustVerifyEmailContract; use Illuminate\Foundation\Auth\Access\Authorizable; class User implements AuthenticatableContract, AuthorizableContract, CanResetPasswordContract, MustVerifyEmailContract { use Authorizable; private UserId $id; private UserRepository $repository; 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 class User implements AuthenticatableContract, AuthorizableContract, CanResetPasswordContract, MustVerifyEmailContract use Domain\User\UserId; 1 use Domain\User\UserNotifier; 2 use Domain\User\UserRepository; 3 use Illuminate\Contracts\Auth\Access\Authorizable as AuthorizableContract; 4 use Illuminate\Contracts\Auth\Authenticatable as AuthenticatableContract; 5 use Illuminate\Contracts\Auth\CanResetPassword as CanResetPasswordContract; 6 use Illuminate\Contracts\Auth\MustVerifyEmail as MustVerifyEmailContract; 7 use Illuminate\Foundation\Auth\Access\Authorizable; 8 9 10 11 12 13 14 { 15 use Authorizable; 16 17 private UserId $id; 18 private UserRepository $repository; 19 private UserId $id; private UserRepository $repository; use Domain\User\UserId; 1 use Domain\User\UserNotifier; 2 use Domain\User\UserRepository; 3 use Illuminate\Contracts\Auth\Access\Authorizable as AuthorizableContract; 4 use Illuminate\Contracts\Auth\Authenticatable as AuthenticatableContract; 5 use Illuminate\Contracts\Auth\CanResetPassword as CanResetPasswordContract; 6 use Illuminate\Contracts\Auth\MustVerifyEmail as MustVerifyEmailContract; 7 use Illuminate\Foundation\Auth\Access\Authorizable; 8 9 class User implements 10 AuthenticatableContract, 11 AuthorizableContract, 12 CanResetPasswordContract, 13 MustVerifyEmailContract 14 { 15 use Authorizable; 16 17 18 19 /** * @inheritDoc */ public function markEmailAsVerified() { return $this->repository->markEmailAsVerified($this->id); } $this->repository = $repository; 28 $this->notifier = $notifier; 29 } 30 31 // ... 32 33 34 35 36 37 38 39 40 41 /** 42 * @inheritDoc 43 */ 44 public function sendEmailVerificationNotification() 45 { 46
  42. App User App\Models\User Eloquent Model と Notifiable への依存がなくなった! Respository と

    Notifier のインターフェースにのみ依存 use Domain\User\UserId; use Domain\User\UserNotifier; use Domain\User\UserRepository; use Illuminate\Contracts\Auth\Access\Authorizable as AuthorizableContract; use Illuminate\Contracts\Auth\Authenticatable as AuthenticatableContract; use Illuminate\Contracts\Auth\CanResetPassword as CanResetPasswordContract; use Illuminate\Contracts\Auth\MustVerifyEmail as MustVerifyEmailContract; use Illuminate\Foundation\Auth\Access\Authorizable; class User implements AuthenticatableContract, AuthorizableContract, CanResetPasswordContract, MustVerifyEmailContract { use Authorizable; private UserId $id; private UserRepository $repository; 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 class User implements AuthenticatableContract, AuthorizableContract, CanResetPasswordContract, MustVerifyEmailContract use Domain\User\UserId; 1 use Domain\User\UserNotifier; 2 use Domain\User\UserRepository; 3 use Illuminate\Contracts\Auth\Access\Authorizable as AuthorizableContract; 4 use Illuminate\Contracts\Auth\Authenticatable as AuthenticatableContract; 5 use Illuminate\Contracts\Auth\CanResetPassword as CanResetPasswordContract; 6 use Illuminate\Contracts\Auth\MustVerifyEmail as MustVerifyEmailContract; 7 use Illuminate\Foundation\Auth\Access\Authorizable; 8 9 10 11 12 13 14 { 15 use Authorizable; 16 17 private UserId $id; 18 private UserRepository $repository; 19 private UserId $id; private UserRepository $repository; use Domain\User\UserId; 1 use Domain\User\UserNotifier; 2 use Domain\User\UserRepository; 3 use Illuminate\Contracts\Auth\Access\Authorizable as AuthorizableContract; 4 use Illuminate\Contracts\Auth\Authenticatable as AuthenticatableContract; 5 use Illuminate\Contracts\Auth\CanResetPassword as CanResetPasswordContract; 6 use Illuminate\Contracts\Auth\MustVerifyEmail as MustVerifyEmailContract; 7 use Illuminate\Foundation\Auth\Access\Authorizable; 8 9 class User implements 10 AuthenticatableContract, 11 AuthorizableContract, 12 CanResetPasswordContract, 13 MustVerifyEmailContract 14 { 15 use Authorizable; 16 17 18 19 use Domain\User\UserId; 1 use Domain\User\UserNotifier; 2 use Domain\User\UserRepository; 3 use Illuminate\Contracts\Auth\Access\Authorizable as AuthorizableContract; 4 use Illuminate\Contracts\Auth\Authenticatable as AuthenticatableContract; 5 use Illuminate\Contracts\Auth\CanResetPassword as CanResetPasswordContract; 6 use Illuminate\Contracts\Auth\MustVerifyEmail as MustVerifyEmailContract; 7 use Illuminate\Foundation\Auth\Access\Authorizable; 8 9 class User implements 10 AuthenticatableContract, 11 AuthorizableContract, 12 CanResetPasswordContract, 13 MustVerifyEmailContract 14 { 15 use Authorizable; 16 17 private UserId $id; 18 private UserRepository $repository; 19 /** * @inheritDoc */ public function sendEmailVerificationNotification() { $user = $this->repository->get($this->id); $url = $this->createVerificationUrl(); $this->notifier->sendEmailVerificationNotification($user, $url); } public function markEmailAsVerified() 37 { 38 return $this->repository->markEmailAsVerified($this->id); 39 } 40 41 42 43 44 45 46 47 48 49 50 51 52 private function createVerificationUrl(): string 53 { 54 return URL::temporarySignedRoute( 55
  43. App User App\Models\User Eloquent Model と Notifiable への依存がなくなった! Respository と

    Notifier のインターフェースにのみ依存 use Domain\User\UserId; use Domain\User\UserNotifier; use Domain\User\UserRepository; use Illuminate\Contracts\Auth\Access\Authorizable as AuthorizableContract; use Illuminate\Contracts\Auth\Authenticatable as AuthenticatableContract; use Illuminate\Contracts\Auth\CanResetPassword as CanResetPasswordContract; use Illuminate\Contracts\Auth\MustVerifyEmail as MustVerifyEmailContract; use Illuminate\Foundation\Auth\Access\Authorizable; class User implements AuthenticatableContract, AuthorizableContract, CanResetPasswordContract, MustVerifyEmailContract { use Authorizable; private UserId $id; private UserRepository $repository; 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 class User implements AuthenticatableContract, AuthorizableContract, CanResetPasswordContract, MustVerifyEmailContract use Domain\User\UserId; 1 use Domain\User\UserNotifier; 2 use Domain\User\UserRepository; 3 use Illuminate\Contracts\Auth\Access\Authorizable as AuthorizableContract; 4 use Illuminate\Contracts\Auth\Authenticatable as AuthenticatableContract; 5 use Illuminate\Contracts\Auth\CanResetPassword as CanResetPasswordContract; 6 use Illuminate\Contracts\Auth\MustVerifyEmail as MustVerifyEmailContract; 7 use Illuminate\Foundation\Auth\Access\Authorizable; 8 9 10 11 12 13 14 { 15 use Authorizable; 16 17 private UserId $id; 18 private UserRepository $repository; 19 private UserId $id; private UserRepository $repository; use Domain\User\UserId; 1 use Domain\User\UserNotifier; 2 use Domain\User\UserRepository; 3 use Illuminate\Contracts\Auth\Access\Authorizable as AuthorizableContract; 4 use Illuminate\Contracts\Auth\Authenticatable as AuthenticatableContract; 5 use Illuminate\Contracts\Auth\CanResetPassword as CanResetPasswordContract; 6 use Illuminate\Contracts\Auth\MustVerifyEmail as MustVerifyEmailContract; 7 use Illuminate\Foundation\Auth\Access\Authorizable; 8 9 class User implements 10 AuthenticatableContract, 11 AuthorizableContract, 12 CanResetPasswordContract, 13 MustVerifyEmailContract 14 { 15 use Authorizable; 16 17 18 19 use Domain\User\UserId; 1 use Domain\User\UserNotifier; 2 use Domain\User\UserRepository; 3 use Illuminate\Contracts\Auth\Access\Authorizable as AuthorizableContract; 4 use Illuminate\Contracts\Auth\Authenticatable as AuthenticatableContract; 5 use Illuminate\Contracts\Auth\CanResetPassword as CanResetPasswordContract; 6 use Illuminate\Contracts\Auth\MustVerifyEmail as MustVerifyEmailContract; 7 use Illuminate\Foundation\Auth\Access\Authorizable; 8 9 class User implements 10 AuthenticatableContract, 11 AuthorizableContract, 12 CanResetPasswordContract, 13 MustVerifyEmailContract 14 { 15 use Authorizable; 16 17 private UserId $id; 18 private UserRepository $repository; 19 use Domain\User\UserId; 1 use Domain\User\UserNotifier; 2 use Domain\User\UserRepository; 3 use Illuminate\Contracts\Auth\Access\Authorizable as AuthorizableContract; 4 use Illuminate\Contracts\Auth\Authenticatable as AuthenticatableContract; 5 use Illuminate\Contracts\Auth\CanResetPassword as CanResetPasswordContract; 6 use Illuminate\Contracts\Auth\MustVerifyEmail as MustVerifyEmailContract; 7 use Illuminate\Foundation\Auth\Access\Authorizable; 8 9 class User implements 10 AuthenticatableContract, 11 AuthorizableContract, 12 CanResetPasswordContract, 13 MustVerifyEmailContract 14 { 15 use Authorizable; 16 17 private UserId $id; 18 private UserRepository $repository; 19 private function createVerificationUrl(): string { return URL::temporarySignedRoute( 'verification.verify', Carbon::now()->addMinutes(Config::get('auth.verification.expire', 60)), [ 'id' => $this->id->rawValue(), 'hash' => sha1($this->getEmailForVerification()), ] ); } { 46 $user = $this->repository->get($this->id); 47 $url = $this->createVerificationUrl(); 48 49 $this->notifier->sendEmailVerificationNotification($user, $url); 50 } 51 52 53 54 55 56 57 58 59 60 61 62 63
  44. App User App\Models\User Eloquent Model と Notifiable への依存がなくなった! Respository と

    Notifier のインターフェースにのみ依存 use Domain\User\UserId; use Domain\User\UserNotifier; use Domain\User\UserRepository; use Illuminate\Contracts\Auth\Access\Authorizable as AuthorizableContract; use Illuminate\Contracts\Auth\Authenticatable as AuthenticatableContract; use Illuminate\Contracts\Auth\CanResetPassword as CanResetPasswordContract; use Illuminate\Contracts\Auth\MustVerifyEmail as MustVerifyEmailContract; use Illuminate\Foundation\Auth\Access\Authorizable; class User implements AuthenticatableContract, AuthorizableContract, CanResetPasswordContract, MustVerifyEmailContract { use Authorizable; private UserId $id; private UserRepository $repository; 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 class User implements AuthenticatableContract, AuthorizableContract, CanResetPasswordContract, MustVerifyEmailContract use Domain\User\UserId; 1 use Domain\User\UserNotifier; 2 use Domain\User\UserRepository; 3 use Illuminate\Contracts\Auth\Access\Authorizable as AuthorizableContract; 4 use Illuminate\Contracts\Auth\Authenticatable as AuthenticatableContract; 5 use Illuminate\Contracts\Auth\CanResetPassword as CanResetPasswordContract; 6 use Illuminate\Contracts\Auth\MustVerifyEmail as MustVerifyEmailContract; 7 use Illuminate\Foundation\Auth\Access\Authorizable; 8 9 10 11 12 13 14 { 15 use Authorizable; 16 17 private UserId $id; 18 private UserRepository $repository; 19 private UserId $id; private UserRepository $repository; use Domain\User\UserId; 1 use Domain\User\UserNotifier; 2 use Domain\User\UserRepository; 3 use Illuminate\Contracts\Auth\Access\Authorizable as AuthorizableContract; 4 use Illuminate\Contracts\Auth\Authenticatable as AuthenticatableContract; 5 use Illuminate\Contracts\Auth\CanResetPassword as CanResetPasswordContract; 6 use Illuminate\Contracts\Auth\MustVerifyEmail as MustVerifyEmailContract; 7 use Illuminate\Foundation\Auth\Access\Authorizable; 8 9 class User implements 10 AuthenticatableContract, 11 AuthorizableContract, 12 CanResetPasswordContract, 13 MustVerifyEmailContract 14 { 15 use Authorizable; 16 17 18 19 use Domain\User\UserId; 1 use Domain\User\UserNotifier; 2 use Domain\User\UserRepository; 3 use Illuminate\Contracts\Auth\Access\Authorizable as AuthorizableContract; 4 use Illuminate\Contracts\Auth\Authenticatable as AuthenticatableContract; 5 use Illuminate\Contracts\Auth\CanResetPassword as CanResetPasswordContract; 6 use Illuminate\Contracts\Auth\MustVerifyEmail as MustVerifyEmailContract; 7 use Illuminate\Foundation\Auth\Access\Authorizable; 8 9 class User implements 10 AuthenticatableContract, 11 AuthorizableContract, 12 CanResetPasswordContract, 13 MustVerifyEmailContract 14 { 15 use Authorizable; 16 17 private UserId $id; 18 private UserRepository $repository; 19 use Domain\User\UserId; 1 use Domain\User\UserNotifier; 2 use Domain\User\UserRepository; 3 use Illuminate\Contracts\Auth\Access\Authorizable as AuthorizableContract; 4 use Illuminate\Contracts\Auth\Authenticatable as AuthenticatableContract; 5 use Illuminate\Contracts\Auth\CanResetPassword as CanResetPasswordContract; 6 use Illuminate\Contracts\Auth\MustVerifyEmail as MustVerifyEmailContract; 7 use Illuminate\Foundation\Auth\Access\Authorizable; 8 9 class User implements 10 AuthenticatableContract, 11 AuthorizableContract, 12 CanResetPasswordContract, 13 MustVerifyEmailContract 14 { 15 use Authorizable; 16 17 private UserId $id; 18 private UserRepository $repository; 19 use Domain\User\UserId; 1 use Domain\User\UserNotifier; 2 use Domain\User\UserRepository; 3 use Illuminate\Contracts\Auth\Access\Authorizable as AuthorizableContract; 4 use Illuminate\Contracts\Auth\Authenticatable as AuthenticatableContract; 5 use Illuminate\Contracts\Auth\CanResetPassword as CanResetPasswordContract; 6 use Illuminate\Contracts\Auth\MustVerifyEmail as MustVerifyEmailContract; 7 use Illuminate\Foundation\Auth\Access\Authorizable; 8 9 class User implements 10 AuthenticatableContract, 11 AuthorizableContract, 12 CanResetPasswordContract, 13 MustVerifyEmailContract 14 { 15 use Authorizable; 16 17 private UserId $id; 18 private UserRepository $repository; 19 'id' => $this->id->rawValue(), { 46 $user = $this->repository->get($this->id); 47 $url = $this->createVerificationUrl(); 48 49 $this->notifier->sendEmailVerificationNotification($user, $url); 50 } 51 52 private function createVerificationUrl(): string 53 { 54 return URL::temporarySignedRoute( 55 'verification.verify', 56 Carbon::now()->addMinutes(Config::get('auth.verification.expire', 60)), 57 [ 58 59 'hash' => sha1($this->getEmailForVerification()), 60 ] 61 ); 62 } 63