Symfony2,一对多关系,使用自动新类别创建新任务


Symfony2, one-to-many relation, creating new task with automatic new category

我正在尝试创建新任务,并将此任务分配给预先创建的类别。但问题是,提交此表单后,它将自动创建一个同名的新类别,我在类别列表中选择了该类别,然后Symfony与它们建立了新的关系。我只想在任务对象中分配一个类别ID,而不是创建一个新的类别。下面是任务对象:

<?php
namespace Acme'TaskBundle'Entity;
use Doctrine'ORM'Mapping as ORM;
use Symfony'Component'Validator'Constraints as Assert;
/**
 * @ORM'Entity
 * @ORM'Table(name="tasks") 
 */
class Task
{
    /**
     * @ORM'Id
     * @ORM'Column(type="integer")
     * @ORM'GeneratedValue(strategy="AUTO")
     */
    protected $id;              
    /**
     * @ORM'Column(type="string", length=200)    
     * @Assert'NotBlank(
     *      message = "Task cannot be empty"      
     * )    
     * @Assert'Length(
     *      min = "3",
     *      minMessage = "Task is too short"         
     * )     
     */     
    protected $task;
    /**
     * @ORM'Column(type="datetime")    
     * @Assert'NotBlank()
     * @Assert'Type("'DateTime")
     */
    protected $dueDate;
    /**
     * @Assert'True(message = "You need to agree")    
     */         
    protected $accepted;
    /**
     * @ORM'ManyToOne(targetEntity="Category", inversedBy="tasks", cascade={"persist"})
     * @ORM'JoinColumn(name="category_id", referencedColumnName="id")                        
     */
    protected $category;        
    public function getTask()
    {
        return $this->task;
    }
    public function setTask($task)
    {
        $this->task = $task;
    }
    public function getDueDate()
    {
        return $this->dueDate;
    }
    public function setDueDate('DateTime $dueDate = null)
    {
        $this->dueDate = $dueDate;
    }
    public function getAccepted()
    {
        return $this->accepted;
    }
    public function setAccepted($accepted)
    {
        $this->accepted = (boolean) $accepted;
    }
    /**
     * Get id
     *
     * @return integer 
     */
    public function getId()
    {
        return $this->id;
    }
    /**
     * Set category
     *
     * @param 'Acme'TaskBundle'Entity'Category $category
     * @return Task
     */
    public function setCategory('Acme'TaskBundle'Entity'Category $category = null)
    {
        $this->category = $category;
        return $this;
    }
    /**
     * Get category
     *
     * @return 'Acme'TaskBundle'Entity'Category 
     */
    public function getCategory()
    {
        return $this->category;
    }
}

类别对象:

<?php
namespace Acme'TaskBundle'Entity;
use Doctrine'ORM'Mapping as ORM;
use Symfony'Component'Validator'Constraints as Assert;
/**
 * @ORM'Entity
 * @ORM'Table(name="categories") 
 */
class Category
{
    /**
     * @ORM'Id
     * @ORM'Column(type="integer")
     * @ORM'GeneratedValue(strategy="AUTO")        
     */
    protected $id; 
    /**
     * @ORM'Column(type="string", length=200)  
     * @Assert'NotNull(message="Please select a category", groups = {"adding"})                 
     */         
    protected $name;       
    /**
     * Get id
     *
     * @return integer 
     */
    public function getId()
    {
        return $this->id;
    }
    /**
     * Set name
     *
     * @param string $name
     * @return Category
     */
    public function setName($name)
    {
        $this->name = $name;
        return $this;
    }
    /**
     * Get name
     *
     * @return string 
     */
    public function getName()
    {
        return $this->name;
    }
    public function __toString()
    {
        return strval($this->name);
    }
}

我的数据库表任务:

ID | Task | dueDate | category_id (here is creating doctrine automatic foreign keys between task and category)

和数据库表类别:

ID | Name
+-------------------+
1 | Main category
2 | Second category
如果我创建一个任务,即主类别,

它会将一个新任务添加到数据库中,并将一个名为主类别的新类别添加到数据库中。所以结果是:

Task table:
+----------------------------------------+
1 | My task name | 2013-09-27 00:00:00 | 3

Categories table:
+--------------------+
1 | Main category
2 | Second category
3 | Main category

预期成果:

Task table:
+----------------------------------------+
1 | My task name | 2013-09-27 00:00:00 | 1

Categories table:
+--------------------+
1 | Main category
2 | Second category

请问我该如何解决?

更新

任务类型表单:

<?php
namespace Acme'TaskBundle'Form'Type;
use Symfony'Component'Form'AbstractType;
use Symfony'Component'Form'FormBuilderInterface;
use Symfony'Component'OptionsResolver'OptionsResolverInterface;
use Acme'TaskBundle'Form'Type'Category;
class TaskType extends AbstractType
{
    public function setDefaultOptions(OptionsResolverInterface $resolver)
    {
        $resolver->setDefaults(array(
            'data_class' => 'Acme'TaskBundle'Entity'Task',
            'cascade_validation' => true,
        ));
    }
    public function buildForm(FormBuilderInterface $builder, array $options)
    {
        $builder->add('task', 'text', array('label' => 'Task'))
                ->add('dueDate', 'date', array('label' => 'Date'))
                ->add('category', new CategoryType(), array('validation_groups' => array('adding')))
                ->add('accepted', 'checkbox')
                ->add('save', 'submit', array('label' => 'Send'));
    }
    public function getName()
    {
        return 'task';
    }
}

类别类型形式:

<?php
namespace Acme'TaskBundle'Form'Type;
use Symfony'Component'Form'AbstractType;
use Symfony'Component'Form'FormBuilderInterface;
use Symfony'Component'OptionsResolver'OptionsResolverInterface;
class CategoryType extends AbstractType
{
    public function setDefaultOptions(OptionsResolverInterface $resolver)
    {
        $resolver->setDefaults(array(
            'data_class' => 'Acme'TaskBundle'Entity'Category',
        ));
    }
    public function buildForm(FormBuilderInterface $builder, array $options)
    {
        $builder->add('name', 'entity', array(
                  'class' => 'AcmeTaskBundle:Category',
                  'query_builder' => function($repository) { return $repository->createQueryBuilder('c')->orderBy('c.id', 'ASC'); },
                  'property' => 'name',
                  'empty_value' => 'Choose something',
                  ));
    }
    public function getName()
    {
        return 'category';
    }
}

首先,您必须将列"name"unique定义为类别(ORM''Column)以避免数据库不一致:

class Category
{
    [...]
    /**
     * @ORM'Column(type="string", length=200, unique=true)  
     * @Assert'NotNull(message="Please select a category", groups = {"adding"})                 
     */         
    protected $name;  

然后,要将持久类别添加到您的任务中,您必须找到它并附加到您的实体,因此:

// Find Category
$category = $this->getDoctrine()->getManager()->getRepository('ACMETaskBundle:Category')->findByName("Category Name");
// Add it to task
$myTask->setCategory($category);