簡體   English   中英

ManyToOne字段上的Symfony2 Doctrine2 UniqueEntity被忽略

[英]Symfony2 Doctrine2 UniqueEntity on ManyToOne field is ignored

我在ProjectApplication之間具有OneToMany關系,並且我想確保兩個Application不能在Project具有相同的名稱。

我試圖像應該配置的那樣配置實體,表單類型和控制器,但是對於重復輸入,我遇到了完整性沖突,因此我認為驗證過程被忽略了。

有人可以告訴我我想念什么嗎?

我的Application實體是這樣的:

namespace App\MainBundle\Entity;

use Doctrine\ORM\Mapping as ORM;
use Doctrine\Common\Collections\ArrayCollection;
use Symfony\Component\Validator\Constraints as Assert;
use Symfony\Bridge\Doctrine\Validator\Constraints\UniqueEntity;
use JsonSerializable;

/**
 * @ORM\Entity
 * @ORM\Table(name="application", uniqueConstraints={@ORM\UniqueConstraint(name="IDX_Unique", columns={"name", "project_id"})})
 * @UniqueEntity(
 *      fields={"name", "project"},
 *      message="Name already used in this project.",
 *      groups="application"
 * )
 */
class Application implements JsonSerializable {

    /**
     * @ORM\Column(type="integer")
     * @ORM\Id
     * @ORM\GeneratedValue(strategy="AUTO")
     */
    protected $id;

    /**
     * @ORM\Column(type="string")
     * @Assert\NotBlank(
     *      message = "Name cannot be empty."
     * )
     * @Assert\Length(
     *      min = "3",
     *      max = "50",
     *      minMessage = "Name is too short. It should have {{ limit }} characters or more.",
     *      maxMessage = "Name is too long. It should have {{ limit }} characters or less."
     * )
     */
    protected $name;

    // other properties ...

    /**
     * @ORM\ManyToOne(targetEntity="Project", inversedBy="applications")
     * @ORM\JoinColumn(name="project_id", referencedColumnName="id")
     */
    protected $project;

    // constructor, methods, getters, setters
}

我的ApplicationType類如下所示:

namespace App\MainBundle\Form\Type;

use Symfony\Component\Form\AbstractType;
use Symfony\Component\Form\FormBuilderInterface;
use Symfony\Component\OptionsResolver\OptionsResolverInterface;

class ApplicationType extends AbstractType {

    public function buildForm(FormBuilderInterface $builder, array $options) {
        $builder->add('name', 'text', array(
            'icon' => 'pencil'
        ));
        $builder->add('description', 'textarea', array(
            'required' => false,
            'icon' => 'info'
        ));
        $builder->add('url', 'url', array(
            'required' => false,
            'icon' => 'link'
        ));
    }

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

    public function setDefaultOptions(OptionsResolverInterface $resolver) {
        $resolver->setDefaults(array(
            'data_class' => 'App\MainBundle\Entity\Application',
            'validation_group' => array('application'),
            'cascade_validation' => true
        ));
    }
}

在我的Controller ,操作如下所示:

/**
 * @Route("/project/{id}/application/add",
 *      name="app_add_application_ajax",
 *      requirements={"_method" = "post"},
 *      options={"expose" = true }
 * )
 * @Secure(roles="ROLE_SUPER_ADMIN")
 * @ParamConverter("project", class="AppMainBundle:Project")
 */
public function addApplicationAction(Project $project, Request $request) {
    $ajaxResponse = array();
    $em = $this->getDoctrine()->getManager();
    if ($request->getMethod() == 'POST' && $request->isXmlHttpRequest()) {
        $formApp = new Application();
        $formApp->setProject($project);
        $form = $this->createForm(new ApplicationType(), $formApp);
        $form->handleRequest($request);
        if ($form->isValid()) {
            $application = $form->getData();
            $em->persist($application);
            $em->flush();
            // build ajax response ...
        } else {
            $ajaxResponse['error'] = $this->getErrorsAsString();
        }
    }
    $response = new Response(json_encode($ajaxResponse));
    $response->headers->set('Content-Type', 'application/json');
    return $response;
}

您的問題是您在表單類型中配置了一個validation_group選項,而Symfony使用的選項是validation_groups 您不會收到有關未知選項的錯誤,因為您是在表單類型的默認選項中進行設置的,因此您將選項標記為已定義(但它是單獨的)。
因此,驗證器與默認組一起運行,它將驗證不同的約束(對name屬性長度的約束位於默認組中)。

請注意,您還有第二個問題,一旦運行約束,該問題就會出現。
您的驗證約束與您擁有的數據庫約束不匹配。 您要求驗證者具有唯一的名稱和唯一的項目,而不是唯一的元組(名稱,項目)。 因此,您會拒絕太多的事情(名稱將在全球范圍內(而不是在每個項目中)被驗證為唯一)。 這是因為您使用2個單獨的UniqueEntity約束,而不是要求多個字段的元組唯一的約束。

暫無
暫無

聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.

 
粵ICP備18138465號  © 2020-2024 STACKOOM.COM