Good day! Just started learning Symfony on my own.
I'm making a news portal. The administrator can download news from an Excel file. I am converting a file to an associative array. For example:
[ 'Title' => 'Some title',
'Text' => 'Some text',
'User' => '[email protected]',
'Image' => 'https://loremflickr.com/640/360'
]
Next, I want to send this array to the form and use 'constraints' to validate it. There are no problems with the fields 'Title', 'Text', 'Image'. I don't know how to properly check the 'User' field. The user in the file is submitting an Email, but I want to check that a user with that Email exists in the database.
NewsImportType
class NewsImportType extends AbstractType
{
public function buildForm(FormBuilderInterface $builder, array $options)
{
$builder
->add('title', TextType::class, [
'constraints' =>
[
new NotBlank(),
new Length(['min' => 256])
],
])
->add('text', TextareaType::class, [
'constraints' =>
[
new NotBlank(),
new Length(['max' => 1000])
],
])
->add('user', TextType::class, [
'constraints' =>
[
new NotBlank(),
new Email(),
],
->add('image', TextType::class, [
'constraints' =>
[
new NotBlank(),
new Length(['max' => 256]),
new Url()
],
]);
}
public function configureOptions(OptionsResolver $resolver): void
{
$resolver->setDefaults([
'allow_extra_fields' => true,
'data_class' => News::class,
]);
}
}
The entities User and News are connected by a One-to-Many relationship.
I was thinking about using ChoiceType and calling UserRepository somehow, but I don't understand how to apply it correctly.
Please tell me how to correctly write 'constraint' for the 'user' field. thank!
CodePudding user response:
Create a Custom Constraint. This way it is reusable in any other form you would like to check for a user.
Create a new folder in your project src/Validator
then put these 2 files in there.
The Constraint
// src/Validator/userAccountExists.php
namespace App\Validator;
use Symfony\Component\Validator\Constraint;
class UserAccountExists extends Constraint
{
public $message = 'User account does\'t exists. Please check the email address and try again.';
}
The Validator
// src/Validator/userAccountExistsValidator.php
namespace App\Validator;
use Symfony\Component\Validator\Constraint;
use Symfony\Component\Validator\ConstraintValidator;
use Symfony\Component\Validator\Exception\UnexpectedTypeException;
use Symfony\Component\Validator\Exception\UnexpectedValueException;
use Doctrine\ORM\EntityManagerInterface;
use App\Entity\User;
class UserAccountExistsValidator extends ConstraintValidator
{
private $entityManager;
public function __construct(EntityManagerInterface $entityManager)
{
$this->entityManager = $entityManager;
}
public function validate($email, Constraint $constraint)
{
if (!$constraint instanceof UserAccountExists) {
throw new UnexpectedTypeException($constraint, UserAccountExists::class);
}
if (null === $email || '' === $email) {
return;
}
if (!is_string($email)) {
throw new UnexpectedValueException($email, 'string');
}
if (!$this->userExists($email)) {
$this->context->buildViolation($constraint->message)->addViolation();
}
}
private function userExists(string $email): bool
{
$user = $this->entityManager->getRepository(User::class)->findOneBy(array('email' => $email));
return null !== $user;
}
}
In your form you can now use the validator
->add('user', TextType::class, [
'constraints' =>
[
new NotBlank(),
new Email(),
new UserAccountExists(),
],
Remember to add use App\Validator\UserAccountExists;
to your form.
CodePudding user response:
You need to use the EntityType field type for your user. This way the form will expect a User object
$builder->add('user', EntityType::class, [
'class' => User::class
]);
And in your controller you can get the user object like this:
$data = [
'Title' => 'Some title',
'Text' => 'Some text',
'User' => '[email protected]',
'Image' => 'https://loremflickr.com/640/360'
];
// serach user by email
$user = $this->getDoctrine()->getManager()->getRepository(User::class)->findOneBy(['email'=>$data['User']]);
if($user){
// do something ...
}