Реализуя связку Repostory + Service + FormModel столкнулся с проблемой проверки уникальности некоторых полей.
Вариант с проверкой в сервисе отпал, т.к. валидация происходит до создания сервиса, да и выкидывать исключения с одной стороны удобно, но вот проблема с проверкой всех полей, да и не хочется отказываться от ajax валидации и других плюшек.
В итоге, немного поразмыслив пришёл с некоторому решению проблемы и хотелось бы услышать мнение о правильности такой реализации.
FormModel
Код: Выделить всё
class UserForm extends Model
{
protected $login;
protected $password;
protected $email;
protected $repository;
protected $uniqueValidator;
public function __construct(UserRepositoryInterface $repository, array $config = [])
{
$this->repository = $repository;
parent::__construct($config);
}
public function rules()
{
return [
['login', 'isLoginUnique'],
['email', 'isEmailUnique'],
[['login', 'password', 'email'], 'safe']
];
}
public function getLogin()
{
return (string) $this->login;
}
public function setLogin($login)
{
$this->login = (string) $login;
}
public function getPassword()
{
return (string) $this->password;
}
public function setPassword($password)
{
$this->password = (string) $password;
}
public function getEmail()
{
return (string) $this->email;
}
public function setEmail($email)
{
$this->email = (string) $email;
}
public function isLoginUnique($attribute, $params)
{
return $this->getUniqueValidator()->isLoginUnique();
}
public function isEmailUnique($attribute, $params)
{
return $this->getUniqueValidator()->isEmailUnique();
}
protected function getUniqueValidator()
{
if(!$this->uniqueValidator) {
$this->uniqueValidator = new UserUniqueValidator($this, $this->repository);
}
return $this->uniqueValidator;
}
}
Код: Выделить всё
class UserUniqueValidator
{
protected $form;
protected $repository;
protected $entity;
public function __construct(UserForm $form, UserRepositoryInterface $repository, User $entity = null)
{
$this->form = $form;
$this->repository = $repository;
$this->entity = $entity;
}
public function isLoginUnique(): bool
{
if($this->entity !== null && $this->entity->getLogin() === $this->form->getLogin()) {
return true;
} else {
$criteria = new UserCriteria();
$criteria->loginEquals($this->form->getLogin());
if($this->repository->exist($criteria)) {
$this->form->addError('login', 'Логин уже занят');
return false;
} else {
return true;
}
}
}
public function isEmailUnique(): bool
{
if($this->entity !== null && $this->entity->getEmail() === $this->form->getEmail()) {
return true;
} else {
$criteria = new UserCriteria();
$criteria->emailEquals($this->form->getEmail());
if($this->repository->exist($criteria)) {
$this->form->addError('email', 'E-mail уже занят');
return false;
} else {
return true;
}
}
}
}