忽略 ManyToOne 实体上的 Symfony2/Doctrine UniqueEntity

标签 symfony doctrine-orm unique-constraint

我有与“项目”相关的“角色”。 我不在乎角色名称是否重复,但我想确保的是,对于每个项目,角色名称不能重复。

这是我认为应该起作用的:

<?php
// src/AppBundle/Entity/Role.php

namespace AppBundle\Entity;

use Doctrine\ORM\Mapping as ORM;
use Symfony\Bridge\Doctrine\Validator\Constraints\UniqueEntity;

/**
 * @ORM\Entity(repositoryClass="AppBundle\Entity\RoleRepository")
 * @ORM\Table(name="roles")
 * @UniqueEntity(fields={"name","project"}, message="Duplicated role for this project")
 */
class Role
{
/**
 * @ORM\Column(type="integer")
 * @ORM\Id
 * @ORM\GeneratedValue(strategy="AUTO")
 */
protected $id;

/**
 * @ORM\Column(type="string", length=100)
 */
protected $name;

/**
 * @ORM\Column(type="text")
 */
protected $description;

...
other fields
...

/**
 * @ORM\ManyToOne(targetEntity="Project")
 */
protected $project;
}

根据文档here这正是我所需要的:

This required option is the field (or list of fields) on which this entity should be unique. For example, if you specified both the email and name field in a single UniqueEntity constraint, then it would enforce that the combination value where unique (e.g. two users could have the same email, as long as they don't have the same name also).

该约束被忽略(我的意思是,如果我尝试为同一个项目使用相同的角色名称,它会存储重复的角色名称和项目ID)。

我错过了什么?

编辑:在我用“php app/consoledoctrine:schema:update --force”更新数据库后,我尝试直接使用 SQL 生成错误,但没有抛出异常。现在,我不知道这个“UniqueEntity”验证是在数据库级别完成的还是 Doctrine 的验证器。

编辑2:我尝试只有一个字段(“名称”)并且验证工作正常(当然仅在该字段上)。 我还尝试对“名称”和“描述”字段进行验证,它有效!所以基本上它不会验证要验证的字段是否是指向另一个表的ID。

无论如何,这是 Controller :

/**
 * @Route("/role/create/{projectID}", name="role_create")
 */
public function createRoleAction(Request $request, $projectID)
{
    $prj = $this->getDoctrine()->getRepository('AppBundle:Project')->findOneById($projectID);

    $role = new Role();
    $form = $this->createForm(new RoleFormType(), $role);

    $form->handleRequest($request);

    if ($form->isValid())
        {
        $em = $this->getDoctrine()->getManager();
        $role->setProject($prj);
        $em->persist($role);
        $em->flush();
        return $this->redirect($this->generateUrl('hr_manage', array('projectID' => $projectID)));
        }

return $this->render('Role/createForm.html.twig', array('projectID' => $projectID, 'form' => $form->createView(),));
}

不执行验证,实体保留在数据库上,“项目”列指向正确的项目。以下是 2 个相关字段的快照: enter image description here

这是 RoleFormType(相关字段的摘录):

<?php
namespace AppBundle\Form\Type;
use Symfony\Component\Form\AbstractType;
use Symfony\Component\Form\FormBuilderInterface;
use Symfony\Component\OptionsResolver\OptionsResolverInterface;

class RoleFormType extends AbstractType
{
public function buildForm(FormBuilderInterface $builder, array $options)
{
    // add your custom field
    $builder->add('name', 'text')
            ->add('description', 'text')
            ...lots of other fields, but "project" is not present as it's passed automatically from the controller
            ->add('save', 'submit', array('label' => 'Create'));

}

public function getName()
{
    return 'role';
}

public function setDefaultOptions(OptionsResolverInterface $resolver)
{
    $resolver->setDefaults(array('data_class' => 'AppBundle\Entity\Role',));
}

}

最佳答案

问题是您实际上并没有验证实体来检查唯一约束违规。当您调用 $form->isValid() 时,它会调用 Role 实体的验证器,因为您将其作为表单的数据类传递。但是,由于 project 在此之后才设置,因此 project 字段不会发生验证。

当您调用 $em->persist($role);$em->flush(); 时,这只是告诉 Doctrine 将实体插入数据库。这 2 个调用自行执行验证,因此将插入重复项。

尝试在创建表单之前设置项目:

$role = new Role();
$role->setProject($prj);

$form = $this->createForm(new RoleFormType(), $role);

现在项目将在实体上设置,因此当调用 $form->isValid() 时,Symfony 验证器将检查唯一性。

如果这不起作用,您还需要将 project 类型作为 hidden 字段添加到表单中,以便将其传回,但我不这样做我认为没有必要。

我要说的另一件事是,您肯定想在数据库本身上添加唯一约束 - 这样,即使您尝试插入重复项,数据库也会向您抛出异常并且不允许这样做,无论如何您的代码。

关于忽略 ManyToOne 实体上的 Symfony2/Doctrine UniqueEntity,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/27744363/

相关文章:

MySQL:唯一约束多列性能优化

mysql - 独特的用户识别约束

php - 如何在 symfony 中将 404 重定向到主页?

mysql - DQL 无法在 FROM 子句中指定目标表 'user_addresses' 进行更新

php - FosUserBundle不将数据保存在mongodb数据库中

mysql - 如何使用查询生成器基于实际字段中的表进行条件 mysql 左连接

php - 在扩展另一个实体的实体中使用鉴别器

properties - 在 neo4j 中对多个属性创建约束

php - 在模板的 Symfony 翻译中使用 Twig 变量

php - Symfony 文件字段在编辑时为空