Можно ли заставить doctrine валидировать поля при создании сущности?

Доктрина создает сущности при помощи рeфлексии, в обход конструктора и сеттеров. Видимо предполагается, что состояние, хранящееся в БД, всегда валидно. Но так бывает не всегда. Иногда приходится лазить в БД в обход всей бизнес-логики, что в свою очередь иногда приводит к ошибкам.

Например, в БД есть nullable поле `name`, которое в сущности не должно быть nullable, и в геттере указано public function getName(): string, и если в БД руками проставить null, то ошибка возникает только при запросе этого геттера. А мне бы хотелось бы выбросить какой-нибудь эксепшн ещё в момент создания сущности.
  • Вопрос задан
  • 284 просмотра
Решения вопроса 1
voronkovich
@voronkovich
1. Вы можете реализовать свой гидратор (hydrator). Гидраторы как раз и занимаются созданием сущностей. Только официальной документации по созданию гидраторов нет. Есть это: https://www.doctrine-project.org/projects/doctrine...
Есть еще старая статья: https://techpunch.co.uk/development/create-custom-...
И статья про гидраторы от Marco Pivetta: https://ocramius.github.io/blog/doctrine-orm-optim...

2. Вы можете подписаться на событие postLoad: https://www.doctrine-project.org/projects/doctrine... и бросать исключение сразу же после создания объекта.

Но, на мой взгляд подобное решение приведет к плохим последствиям т.к. исключение будет бросаться в самых неожиданных местах. Как вы будете его обрабатывать?
Лучше локализуйте проблему там, где она возникает, бросая исключения в коде, не допускающем null-значений:
class UserNotfier
{
    public function notifyUser(User $user): void
    {
        if (null === $user->getEmail()) {
            throw new \Exception('User must have an email!);
        }
        
         // ...
    }
}
Ответ написан
Пригласить эксперта
Ответы на вопрос 1
skobkin
@skobkin
Гентушник, разработчик на PHP и Symfony.
Доктрина создает сущности при помощи рeфлексии, в обход конструктора и сеттеров.

С помощью десериализации. (UPD: см. комменты, уже не актуально)

Видимо предполагается, что состояние, хранящееся в БД, всегда валидно. Но так бывает не всегда.

Это ваша задача этого не допускать. Если вы это допустили, ошибки Doctrine - это меньшее, что может вылезти.

Например, в БД есть nullable поле `name`, которое в сущности не должно быть nullable

Ну так может быть стоит привести схему и сущность с маппингом в соответствие друг другу, а не отстреливать симптомы?

public function getName(): string
и если в БД руками проставить null, то ошибка возникает только при запросе этого геттера.

Решается это так:
public function getName(): ?string

Я сначала было хотел вам предложить валидировать данные на входе в сущность (конструктор), но потом читая ваш вопрос дальше, понял, что вы вообще используете Doctrine очень странно и ждёте, что сама Doctrine будет вам предоставлять средства для ухода от возникающих проблем.
Первое и самое важное: Doctrine - это Data Mapper. Если у вас маппинг и сущность не соответствуют схеме - работать ничего нормально не будет. Лечите заболевание, а не симптомы.
Ответ написан
Ваш ответ на вопрос

Войдите, чтобы написать ответ

Похожие вопросы