Symfony检查输入数据是否唯一

时间:2019-02-06 12:50:00

标签: php mongodb symfony assert

我有一个不带“实体”的自定义验证数组,如下所示:

$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中,我有“用户”集合。我需要检查请求中的“昵称”和“电子邮件”是否唯一。 因此,如何在添加新用户期间向字段添加规则以检查该字段在数据库中是否唯一。 以及如何在当前用户ID的用户更新详细信息期间忽略检查唯一字段?

谢谢。

1 个答案:

答案 0 :(得分:0)

根据文档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
    }

}

更新:要在没有实体的情况下进行操作, 根据本文档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相似。 我希望这种解决方案的尝试能对您有所帮助。