Symfony3: Doctrine Transaction и EventSubscriber - PullRequest
0 голосов
/ 20 марта 2019

Я пишу метод в моем приложении Symfony 3 для массового создания пользователей.Поток загружает CSV-файл со всеми необходимыми данными.

Я создал службу, в которую я записываю всю логику этой операции.Это мой сервис:

class BulkRegistration
{
    private $em;
    private $validator;
    private $session;

    public function __construct(EntityManagerInterface $em, ValidatorInterface $validator, SessionInterface $session)
    {
        $this->em = $em;
        $this->validator = $validator;
        $this->session = $session;
    }

    public function run(BulkRegistrationData $bulkRegistrationData){
        //todo rimuovere dipendenza nascosta
        $serializer = new Serializer([new ObjectNormalizer()], [new CsvEncoder()]);

        $datas = $serializer->decode(file_get_contents($bulkRegistrationData->csv), 'csv');

        $this->em->getConnection()->beginTransaction();

        try{
            foreach($datas as $data)
            {
                $userData = UserData::create($data);
                $this->validate($userData, 'newUser');

                $userCreate = User::create($userData->user);
                $this->em->persist($userCreate);


                $this->em->flush();
            }

            $this->em->getConnection()->commit();

        } catch (\Exception $e) {
            $this->em->getConnection()->rollback();
            $this->em->close();

            $this->session->getFlashBag()->add('error', $e->getMessage());

            return false;
        }

        return true;
    }

    private function validate ($entity, $validationGroup = null){
        if($validationGroup){
            $errors = $this->validator->validate($entity, null, [$validationGroup]);
        }else{
            $errors = $this->validator->validate($entity);
        }

        if (count($errors) > 0) {
            $errorMessage = '';
            foreach($errors as $error)
            {
                $errorMessage .= $error->getMessage();
            }
            throw new \Exception($errorMessage);
        }

        return;
    }
}

Также я написал этот EmailSubscriber для отправки электронного письма активации каждый раз, когда сущность пользователя сохраняется:

class EmailSubscriber implements EventSubscriber
{
    private $activationEmail;

    public function __construct(SendActivationEmail $activationEmail)
    {
        $this->activationEmail = $activationEmail;
    }

    public function getSubscribedEvents()
    {
        return array(
            Events::postPersist,
        );
    }

    public function postPersist(LifecycleEventArgs $args)
    {
        $entity = $args->getObject();
        $entityManager = $args->getObjectManager();

        if ($entity instanceof User)
        {
            $this->activationEmail->send($entity);
        }
    }
}

И это вопрос:

EventSubscriber перехватывает постоянное событие перед фиксацией транзакции.Я хочу или сохраняю всю строку в моей базе данных, или отвечаю с нарушением и прошу Пользователя изменить его CSV-файл.

Поскольку это может быть один из аргументов useCase, отправленных по электронной почте, но не сохраняющих пользователя вDB, например, для какого-то допустимого нарушения одной из строк csv.

Надеюсь, я был в смятении, случай немного запутанный.

1 Ответ

0 голосов
/ 20 марта 2019

Я думаю, вам нужно настроить foreach так, чтобы он очищался только при отсутствии ошибок:

foreach($datas as $data) {
    $userData = UserData::create($data);
    try {
        $this->validate($userData, 'newUser');
    } catch (\Exception $e) {
        $this->em->getConnection()->rollback();
        $this->em->close();

        $this->session->getFlashBag()->add('error', $validation);

        return false;
    }
    $userCreate = User::create($userData->user);
    $this->em->persist($userCreate);
}
$this->em->flush();
$this->em->getConnection()->commit();

return true;
Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...