-
-
Save fesor/33f041e3f362beff8d0ef977afd1ff66 to your computer and use it in GitHub Desktop.
User
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
<?php | |
class RegisterUserHandler | |
{ | |
private $encoder; | |
private $users; | |
private $notificator; | |
public function __construct(PasswordEncoder $encoder, UserRepository $users, Notificator $notificator) | |
{ | |
$this->encoder = $encoder; | |
$this->users = $users; | |
$this->notificator = $notificator; | |
} | |
public function handle(RegisterUserRequest $request) | |
{ | |
$user = (new UserBuilder() | |
->withEmail($request->get('email')) | |
->withPassword($request->get('password', $this->encoder) | |
->withName($request->get('name')) | |
->withBirthDay($request->get('birthday')) | |
->build(); | |
$this->users->add($user); | |
$this->notificator->notify(new UserRegisteredNotification($user)); | |
} | |
} |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
<?php | |
namespace App\Domain\User; | |
class User | |
{ | |
private $id; | |
private $email; | |
private $unconfirmedEmail; | |
private $emailConfirmationToken; | |
private $password; | |
private $passwordsHistory; | |
private $name; | |
private $birthDay; | |
public function __construct(UserBuilder $builder) | |
{ | |
$this->email = $builder->email(); | |
$this->emailConfirmationToken = uuid4(); | |
$this->password = $builder->password(); | |
$this->passwordsHistory = []; | |
$this->name = $builder->name(); | |
$this->birthDay = $builder->birthDay(); | |
} | |
public function changeEmail(string $email, Notificator $notificator) | |
{ | |
$this->unconfirmedEmail = $email; | |
$this->resendConfirmationEmail($notificator); | |
} | |
public function confirmEmail(string $confirmationToken) | |
{ | |
if ($this->emailConfirmationToken !== $confirmationToken) { | |
throw new InvalidConfirmationTokenException(); | |
} | |
$this->emailConfirmationToken = null; | |
} | |
public function resendConfirmationEmail(Notificator $notificator) | |
{ | |
$this->emailConfirmationToken = uuid4(); | |
$notificator->notify(new ConfirmNewEmailAddressNotification($this->unconfirmedEmail, $this->email)); | |
} | |
public function changePassword(string $password, PasswordEncoder $encoder) | |
{ | |
$this->passwordsHistory[] = $this->password; | |
$this->failIfPasswordAlreadyHasBeenUsed(); | |
$this->password = $encoer->encode($password); | |
} | |
private function failIfPasswordAlreadyHasBeenUsed(string $password, PasswordEncoder $encoder) | |
{ | |
foreach ($this->passwordsHistory as $previousPassword) { | |
if ($this->encoder->isPasswordValid($previousPassword, $password) { | |
throw new PasswordIsAlreadyHasBeenUsedException(); | |
} | |
} | |
} | |
} |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
<?php | |
class UserBuilder | |
{ | |
private $email; | |
private $password; | |
private $name; | |
private $birthDay; | |
public function withEmail($email) | |
{ | |
$this->email = $email; | |
return $this; | |
} | |
public function withPassword($password, PasswordEncoder $encoder) | |
{ | |
$this->password = $encoder->encode($password); | |
return $this; | |
} | |
public function withName($name) | |
{ | |
$this->name = $name; | |
return $this; | |
} | |
public function withBirthDay($birthDay) | |
{ | |
$this->birthDay = $birthDay; | |
return $this; | |
} | |
/** | |
* @return mixed | |
*/ | |
public function email() | |
{ | |
return $this->email; | |
} | |
/** | |
* @return mixed | |
*/ | |
public function password() | |
{ | |
return $this->password; | |
} | |
/** | |
* @return mixed | |
*/ | |
public function name() | |
{ | |
return $this->name; | |
} | |
/** | |
* @return mixed | |
*/ | |
public function birthDay() | |
{ | |
return $this->birthDay; | |
} | |
public function build() : User | |
{ | |
if (empty($this->email) | |
|| empty($this->password) | |
|| empty($this->name) { | |
throw \InvalidArgumentException('Fields email, password and name are required'); | |
} | |
return new User($this); | |
} | |
} |
@fesor убедительно, но остается такой момент если делаем вставку не валидного значения с последующим сохранением в бд например через маппер, как быть в данном случае делать еще одну валидацию?
$user->setEmail("incorrenct_mail");//или даже $user->setEmail(NULL);
try{
$userMapper->save($user);
}catch(Exception $e){
echo $e->getMessage();
}
@dimaxz так, вопервых допущение простое - у тебя никогда не должно быть такого кода, который "меняет состояние сущности и делает ее невалидно". Инварианты объекта всегда должны сохраняться.
->withEmail($request->get('email'))
И на первый взгляд это не сеттер ))
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment
@dimaxz, когда у тебя 10 аргументов в конструкторе - это не дело. Вопервых это не читабельно, во вторых - это не очень гибко (когда у тебя может быть несколько наборов обязательных полей в зависимости от какой-то логики), в третьих - добавь 11-ый аргумент в середину и все сломаешь.
А с билдерами - у тебя все читабельно, правила валидации можно перенести в конструктор, мне просто так не очень нравится, с точки зрения никапсуляции тоже все гуд.