Symfony 检查输入数据是否唯一

Symfony check if input data is unique

我有一个没有 "Entity" 的自定义验证数组,如下所示:

$dataContent = json_decode($request->getContent(), true);

$dataToCheck = [
            'name' => [
                new Assert\Required(),
                new Assert\NotBlank(),
                new Assert\Type('string'),
                new Assert\Length(['min' => 4]),
            ],
            'nick' => [
                new Assert\Required(),
                new Assert\NotBlank(),
                new Assert\Type('string'),
                new Assert\Length(['min' => 4]),
            ],
            'email' => [
                new Assert\Required(),
                new Assert\NotBlank(),
                new Assert\Email(),
            ]
]

$constraint = new Assert\Collection($dataToCheck);
$violations = $validator->validate($dataContent, $constraint);

在 MongoDb 我有 collections "users"。我需要检查请求中的 'nick' 和 'email' 是否唯一。 那么如何向字段添加规则以检查在添加新用户期间该字段在数据库中是否唯一。 以及如何在用户更新当前用户 ID 的详细信息期间忽略检查唯一字段?

谢谢。

根据文档 Registration Form with MongoDB,解决方案之一是像这样进行:

  • 您的用户实体
namespace Acme\AccountBundle\Document;

use Doctrine\ODM\MongoDB\Mapping\Annotations as MongoDB;
use Symfony\Component\Validator\Constraints as Assert;
use Doctrine\Bundle\MongoDBBundle\Validator\Constraints\Unique as MongoDBUnique;

/**
 * @MongoDB\Document(collection="users")
 * @MongoDBUnique(fields="email", groups={"new"})
 * @MongoDBUnique(fields="nick", groups={"new"})
 */
class User
{
   /**
     * @MongoDB\Id
     */
    protected $id;

    /**
     * @MongoDB\Field(type="string")
     * @Assert\NotBlank(groups={"new", "edit"})
     * @Assert\Email(groups={"new", "edit"})
     */
    protected $email;

   /**
     * @MongoDB\Field(type="string")
     * @Assert\NotBlank(groups={"new", "edit"})
     * @Assert\Length(min="4", groups={"new", "edit"})
     */
    protected $nick;

   /**
     * @MongoDB\Field(type="string")
     * @Assert\NotBlank(groups={"new", "edit"})
     * @Assert\Length(min="4", groups={"new", "edit"})
     */
    protected $name;

    public function getId()
    {
        return $this->id;
    }

    public function getEmail()
    {
        return $this->email;
    }

    public function setEmail($email)
    {
        $this->email = $email;
    }

    public function getNick()
    {
        return $this->nick;
    }

    public function setNick($nick)
    {
        $this->nick = $nick;
    }

    public function getName()
    {
        return $this->name;
    }

    public function setName($name)
    {
        $this->name = $name;
    }
}
  • 然后你定义UserType
namespace Acme\AccountBundle\Form\Type;

use Symfony\Component\Form\AbstractType;
use Symfony\Component\Form\Extension\Core\Type\EmailType;
use Symfony\Component\Form\Extension\Core\Type\TextType;
use Symfony\Component\Form\FormBuilderInterface;
use Symfony\Component\OptionsResolver\OptionsResolver;
use Acme\AccountBundle\Document\User;

class UserType extends AbstractType
{
    public function buildForm(FormBuilderInterface $builder, array $options)
    {
        $builder->add('email', EmailType::class)
                ->add('nick', TextType::class)
                ->add('name', TextType::class);
    }

    public function configureOptions(OptionsResolver $resolver)
    {
        $resolver->setDefaults(array(
            'data_class' => User::class,
            'validation_groups' => ['new', 'edit']
        ));
    }
}

您使用验证组是因为,根据您所说,您不想验证用于更新的唯一字段,您只想为创建验证。

  • 最后在控制器中你可以做:
namespace Acme\AccountBundle\Controller;

use Symfony\Bundle\FrameworkBundle\Controller\Controller;
use Symfony\Component\HttpFoundation\Response;

use Acme\AccountBundle\Form\Type\UserType;
use Acme\AccountBundle\Document\User;
use Symfony\Component\Routing\Annotation\Route;
use Sensio\Bundle\FrameworkExtraBundle\Configuration\Security;

class AccountController extends Controller
{
    /**
     * @Route("/users/create", name="app_users_create)
     */
    public function createAction()
    {

        $dataContent = json_decode($request->getContent(), true);
        if ($dataContent === null || !is_array($dataContent)) {
             // Throw exception for invalid format request
        }
        $dm = $this->get('doctrine_mongodb')->getManager();
        $user = new User();

        $form = $this->createForm(UserType::class, $user);    
        $form->submit($dataContent);

        if ($form->isSubmitted() && $form->isValid()) {

           $dm->persist($user);
           $dm->flush();

           // Return something for success
        }

        // Return Form error
    }

    /**
     * @Route("/users/edit", name="app_users_edit)
     * @Security("is_granted('IS_AUTHENTICATED_REMEMBERED')")
     */
    public function updateAction()
    {

        $dataContent = json_decode($request->getContent(), true);
        if ($dataContent === null || !is_array($dataContent)) {
             // Throw exception for invalid format request
        }
        $dm = $this->get('doctrine_mongodb')->getManager();
        $user = $this->getUser();

        $form = $this->createForm(UserType::class, $user);    
        $form->submit($dataContent); 

        if ($form->isSubmitted() && $form->isValid()) {

           $dm->flush();

           // Return something for success
        }

        // Return Form error
    }

}

Update :要在没有实体的情况下进行, 根据此文档 CustomContraint,您可以使用自定义约束名称(如 UniqueCustom)并将其添加到约束数组中。在此自定义约束(UniqueCustom)中,您可以检查相应的电子邮件(或昵称)是否已存在于您的 MongoDB 中。要忽略此更新检查,您可以像上面那样使用验证组。所以你的约束数组就像(这只是一个想法):

$dataToCheck = [
            'email' => [
                new Assert\Required(['groups' => ['new', 'edit']]),
                new Assert\NotBlank(['groups' => ['new', 'edit']]),
                new Assert\Type('string'),
                new Assert\Email(['groups' => ['new', 'edit']]),
                new UniqCustom(['groups' => ['new']]) // Custom uniq constraint
            ],
            'nick' => [
                new Assert\Required(['groups' => ['new', 'edit']]),
                new Assert\NotBlank(['groups' => ['new', 'edit']]),
                new Assert\Type('string'),
                new Assert\Length(['min' => 4, 'groups' => ['new', 'edit']]),
                new UniqCustom(['groups' => ['new']])
            ],
            'name' => [
                new Assert\Required(['groups' => ['new', 'edit']]),
                new Assert\NotBlank(['groups' => ['new', 'edit']]),
                new Assert\Type('string'),
                new Assert\Length(['min' => 4, 'groups' => ['new', 'edit']]),
            ],

        ];

ODM 的过程类似于用户 ORM。 希望这个解决方案的尝试可以帮到你。