A
A
Alexey Verkhovtsev2019-04-03 20:28:23
symfony
Alexey Verkhovtsev, 2019-04-03 20:28:23

Check entities for uniqueness by field Symfony 4?

I have a form class

<?php

namespace App\Form;

use App\Mapper\ProfileMapper;
use Symfony\Component\DependencyInjection\ContainerInterface;
use Symfony\Component\Form\AbstractType;
use Symfony\Component\Form\Extension\Core\Type\EmailType;
use Symfony\Component\Form\Extension\Core\Type\FileType;
use Symfony\Component\Form\Extension\Core\Type\PasswordType;
use Symfony\Component\Form\Extension\Core\Type\RepeatedType;
use Symfony\Component\Form\Extension\Core\Type\SubmitType;
use Symfony\Component\Form\Extension\Core\Type\TextType;
use Symfony\Component\Form\FormBuilderInterface;
use Symfony\Component\OptionsResolver\OptionsResolver;
use Symfony\Component\Security\Core\Validator\Constraints\UserPassword;
use Symfony\Component\Validator\Constraints\Image;
use Symfony\Component\Validator\Constraints\NotBlank;

final class UserType extends AbstractType
{
    /**
     * @var ContainerInterface
     */
    private $container;

    public function __construct(ContainerInterface $container)
    {
        $this->container = $container;
    }

    public function buildForm(FormBuilderInterface $builder, array $options)
    {
        $allowedMimeTypes = $this->container->getParameter(
            'allowed_mime_types'
        );
        $allowedMimeTypesString = implode(', ', $allowedMimeTypes);
        $builder
            ->add('firstName', TextType::class)
            ->add('lastName', TextType::class)
            ->add('username', TextType::class)
            ->add('email', EmailType::class)
            ->add('imageFile', FileType::class, [
                'constraints' => [
                    new Image(
                        [
                            'mimeTypes' => $allowedMimeTypes,
                            'maxSize' => $this->container->getParameter(
                                'max_uploaded_avatar_size'
                            ),
                            'mimeTypesMessage' =>
                                'allowed image
                                formats are ('. $allowedMimeTypesString .')'
                        ]
                    )
                ]
            ])
            ->add('currentPassword', PasswordType::class, [
                'mapped' => false,
                'constraints' => [
                    new NotBlank(),
                    new UserPassword()
                ]
            ])
            ->add('plainPassword', RepeatedType::class, [
                'type' => PasswordType::class,
                'invalid_message' => 'The New Password and
                    New Password Repeat must match'
            ])
            ->add('submit', SubmitType::class)
            ->setDataMapper(new ProfileMapper());
    }

    public function configureOptions(OptionsResolver $resolver): void
    {
        $resolver->setDefaults([
            'empty_data' => null
        ]);
    }
}

There is a Data Mapper
<?php

namespace App\Mapper;

use App\DTO\ProfileDto;
use App\Exception\InvalidTypeException;
use Symfony\Component\Form\DataMapperInterface;
use Symfony\Component\Form\FormInterface;

final class ProfileMapper implements DataMapperInterface
{
    /**
     * @param mixed $data
     * @param FormInterface[]|\Traversable $forms
     * @throws InvalidTypeException
     */
    public function mapDataToForms($data, $forms)
    {
        if (is_null($data)) {
            return;
        }

        //if (!$data instanceof ProfileDto) {
            //throw new InvalidTypeException();
        //}

        /** @var FormInterface[]|\Traversable $forms */
        $forms = iterator_to_array($forms);

        $forms['firstName']->setData($data->getFirstName());
        $forms['lastName']->setData($data->getLastName());
        $forms['username']->setData($data->getUsername());
        $forms['email']->setData($data->getEmail());
        $forms['plainPassword']->setData($data->getPlainPassword());
        $forms['imageFile']->setData($data->getImageFile());
    }

    public function mapFormsToData($forms, &$data)
    {
        /** @var FormInterface[]|\Traversable $forms */
        $forms = iterator_to_array($forms);

        $data = new ProfileDto(
            $forms['firstName']->getData(),
            $forms['lastName']->getData(),
            $forms['username']->getData(),
            $forms['email']->getData(),
            $forms['plainPassword']->getData(),
            $forms['imageFile']->getData()
        );
    }
}

+ DTO itself
Creating a form in the controller
/** @var User $user */
        $user = $security->getUser();
        $form = $this->createForm(UserType::class, $user);

In this case, I do all the validation in the config/validator/validation.yml file for DTO
App\DTO\ProfileDto:
    constraints:
        - Symfony\Bridge\Doctrine\Validator\Constraints\UniqueEntity:
            fields: [email, workspace_id]
            entityClass: App\Repository\User\DoctrineUserRepository
            em: doctrine.orm.default_entity_manager
    properties:
        firstName:
            - NotBlank:
            - Length:
                min: 2
                max: 255

I transferred the user's repository there and the entity manager was needed, transferred it, but writes that this was not found. Am I sending something wrong?
Thanks in advance!

Answer the question

In order to leave comments, you need to log in

1 answer(s)
B
BoShurik, 2019-04-03
@seftomsk

UniqueEntityonly works with Entity . If you want to validate a DTO this way, you will have to write your own validator. You can use the built-in as a basis: https://github.com/symfony/symfony/blob/master/src...
I use something like this: https://gist.github.com/BoShurik/df63d1f51bc01465e...

Didn't find what you were looking for?

Ask your question

Ask a Question

731 491 924 answers to any question