3

I am trying to implement Embedded Forms (Symfony2, 2.7), with Task and Tag entities, One2Many.

To save reference to the Task object into a Tag record, I am able to define Task's createAction() only by:

/**
 * Creates a new Task entity.
 *
 * @Route("/", name="MyName_Task_create")
 * @Method("POST")
 * @Template("MyNameBundleBlogBundle:Task:new.html.twig")
 */
public function createAction(Request $request)
{
    $task = new Task();
    $form = $this->createCreateForm($task);
    $form->handleRequest($request);

    if ($form->isValid()) {
        $em = $this->getDoctrine()->getManager();
        $tags = $task->getTags();
        foreach($tags as $tg){$tg->setTask($task); $em->persist($tg);}   // <-- do I really need to loop?
        $em->persist($task);
        $em->flush();

        return $this->redirect($this->generateUrl('MyName_Task_show', array('id' => $task->getId())));
    }

    return array(
        'entity' => $task,
        'form'   => $form->createView(),
    );
}

EDIT: I know it should work without the loop straightforwardly, but it does not. Question is: What should I look for which I might have written wrong? See related question

Note, I have:

class Task{
....
 /**
 *
 * @ORM\OneToMany(targetEntity="Tag", mappedBy="Task", cascade={"persist"} )
 */
private $Tags;
....
 /**
 * Add tag
 *
 * @param \MyName\Bundle\BlogBundle\Entity\Tag $tag
 *
 * @return Task
 */
public function addTag(\MyName\Bundle\BlogBundle\Entity\Tag $tag)
{
    $this->tags[] = $tag;
    $tag->setTask($this);
    return $this;
}
}
7
  • 2
    Persisting the task is all you need to do. The cascade=persist will take care of persisting the tags. Commented Feb 2, 2016 at 21:18
  • Thanks. Actually, I have a three layers Job/Task/Tag situation. Does it make a difference? I'll try to fix, or make another question. Commented Feb 3, 2016 at 16:29
  • 1
    As long as you have your cascade=persist set correctly on your relations then one persist is all you need. Commented Feb 3, 2016 at 16:31
  • @Cerad, all, if you spot something wrong stackoverflow.com/questions/35225089/…, I appreciate Commented Feb 5, 2016 at 13:15
  • 1
    Before starting a new question you really should finish this one. You have two correct answers. Really should accept one or state why not. Commented Feb 5, 2016 at 13:30

2 Answers 2

1

No, you don't need to loop through all tags and explicitly set task, Symfony will do that for you if you configure it correctly.

The only thing you need to add is set by_reference to false inside your form builder. In this case, symfony will explicitly will call setTask on every tag.

For more info 'by_reference'

Sign up to request clarification or add additional context in comments.

3 Comments

No need for by_reference here. His setTag implementation takes care of the cross referencing.
He can remove that line too.
Not sure which line you are talking about but the $tag->setTask($this) line should stay and makes keeping the object references in sync much easier.
0

According to @Cerad comment, the only thing you have to do is persist the Task.

All related tags will be automatically persisted, thanks to cascade={"persist"} in your association mapping.

Your code should be :

if ($form->isValid()) {
    $em = $this->getDoctrine()->getManager();
    $em->persist($task);
    $em->flush();

    return $this->redirect($this->generateUrl('MyName_Task_show', array('id' => $task->getId())));
}

See the Etablishing associations and Cascade operations chapters of Doctrine documentation.

Comments

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.