Проверка уникальности полей Repostory + Service + FormModel

Обсуждаем, как правильно строить приложения
Ответить
Аватара пользователя
BrusSENS
Сообщения: 565
Зарегистрирован: 2012.07.26, 06:51
Откуда: Новороссийск
Контактная информация:

Проверка уникальности полей Repostory + Service + FormModel

Сообщение BrusSENS »

Доброго времени всем!
Реализуя связку 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;
    }
}
UserUniqueValidator - по сути простой сервис

Код: Выделить всё

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;
            }
        }
    }
}
Native Web - небольшой блог о веб разработке (временно на ремонте)
Режим обслуживания сайта для Yii 2.x.x
Аватара пользователя
ElisDN
Сообщения: 5845
Зарегистрирован: 2012.10.07, 10:24
Контактная информация:

Re: Проверка уникальности полей Repostory + Service + FormModel

Сообщение ElisDN »

Код: Выделить всё

class SignupForm extends Model
{
    public $login;
    public $email;
    public $password;

    private $repository;

    public function __construct(UserRepository $repository, array $config = [])
    {
        $this->repository = $repository;
        parent::__construct($config);
    }

    public function rules()
    {
        return [
            ['login', 'isLoginUnique'],
            ['email', 'isEmailUnique'],
            [['login', 'password', 'email'], 'safe']
        ];
    }

    public function isLoginUnique($attribute, $params)
    {
        if ($this->repository->existsByLogin($this->$attribute)) {
            $this->addError($attribute, 'Login уже занят');
        }
    }

    public function isEmailUnique($attribute, $params)
    {        
        if ($this->repository->existsByEmail($this->$attribute)) {
            $this->addError($attribute, 'E-mail уже занят');
        }
    }
}
Аватара пользователя
BrusSENS
Сообщения: 565
Зарегистрирован: 2012.07.26, 06:51
Откуда: Новороссийск
Контактная информация:

Re: Проверка уникальности полей Repostory + Service + FormModel

Сообщение BrusSENS »

Дмитрий, я думал над таким вариантом, но т.к. из-за обстоятельств буду делать несколько форм на создание, редактирование, регистрацию и т.п., поэтому и решил вынести в отдельный сервис проверку на уникальность, или есть другие варианты решения такой задачи? Всё таки методы проверки уникальности будут несколько отличаться при создании и редактировании.
Ещё хотелось бы поинтересоваться насчёт геттеров и сеттеров для свойств. Хочу, что бы каждое свойство возвращало результат определенного типа, как тогда без геттеров и сеттеров это осуществить "малой кровью"?
Native Web - небольшой блог о веб разработке (временно на ремонте)
Режим обслуживания сайта для Yii 2.x.x
Ответить