Bonjour,

Je réalise un petit bugtracker pour me faire la main sur Symfony2.

J'ai donc une entité Project et une entité Item (qui représente un bug, une tâche...). Elles sont liées entre elles.

Lorsqu'un item change de statut, l'attribut todo du project doit être incrémenté, ou l'inverse. Seulement ça ne fonctionne pas. J'ai utilisé la callback PreUpdate, elle apparemment bien exécutée, mais l'entité project n'est pas mise à jour dans la base de données.

Entité Project (extrait):

<?php

namespace BugTracker\ProjectBundle\Entity;

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

/**
 * Project
 *
 * @ORM\Table()
 * @ORM\Entity(repositoryClass="BugTracker\ProjectBundle\Entity\ProjectRepository")
 *
 * @UniqueEntity("name")
 */
class Project
{   
    /**
     * @var integer
     *
     * @ORM\Column(name="todo", type="integer")
     */
    private $todo;

    /**
     * @ORM\OneToMany(targetEntity="BugTracker\ProjectBundle\Entity\Item", mappedBy="project", cascade={"persist"})
     */
    private $items;

    /**
     * Constructor
     */
    public function __construct()
    {
        $this->items = new \Doctrine\Common\Collections\ArrayCollection();
        $this->todo = 0;
    }

    /**
     * Add items
     *
     * @param \BugTracker\ProjectBundle\Entity\Item $items
     * @return Project
     */
    public function addItem(\BugTracker\ProjectBundle\Entity\Item $items)
    {
        $this->items] = $items;

        return $this;
    }

    /**
     * Remove items
     *
     * @param \BugTracker\ProjectBundle\Entity\Item $items
     */
    public function removeItem(\BugTracker\ProjectBundle\Entity\Item $items)
    {
        $this->items->removeElement($items);
    }

    /**
     * Get items
     *
     * @return \Doctrine\Common\Collections\Collection
     */
    public function getItems()
    {
        return $this->items;
    }

    /**
     * Set todo
     *
     * @param integer $todo
     * @return Project
     */
    public function setTodo($todo)
    {
        $this->todo = $todo;

        return $this;
    }

    /**
     * Get todo
     *
     * @return integer
     */
    public function getTodo()
    {
        return $this->todo;
    }
}

Entité Item (extrait):

<?php

namespace BugTracker\ProjectBundle\Entity;

use Doctrine\ORM\Mapping as ORM;
use Gedmo\Mapping\Annotation as Gedmo;

/**
 * Item
 *
 * @ORM\Table()
 * @ORM\Entity(repositoryClass="BugTracker\ProjectBundle\Entity\ItemRepository")
 * @ORM\HasLifecycleCallbacks()
 */
class Item
{
    /**
     * @var string
     *
     * @ORM\Column(name="status", type="string", length=100)
     */
    private $status;

    /**
     * @ORM\ManyToOne(targetEntity="BugTracker\ProjectBundle\Entity\Project", inversedBy="items", cascade={"persist"})
     *
     * @ORM\JoinColumn(nullable=false)
     */
    private $project;

    private $previousStatus;

    /**
     * Set status
     *
     * @param string $status
     * @return Item
     */
    public function setStatus($status)
    {
        $this->status = $status;

        return $this;
    }

    /**
     * Get status
     *
     * @return string
     */
    public function getStatus()
    {
        return $this->status;
    }

    /**
     * Set project
     *
     * @param \BugTracker\ProjectBundle\Entity\Project $project
     * @return Item
     */
    public function setProject(\BugTracker\ProjectBundle\Entity\Project $project)
    {
        $this->project = $project;

        return $this;
    }

    /**
     * Get project
     *
     * @return \BugTracker\ProjectBundle\Entity\Project
     */
    public function getProject()
    {
        return $this->project;
    }

    /**
     * @ORM\PostLoad
     */
    public function maj()
    {
        $this->previousStatus = $this->status;
    }

    /**
     * @ORM\PrePersist
     */
    public function updateTodo()
    {
        if ($this->getStatus()!=$this->previousStatus) {
            $todo = $this->getProject()->getTodo();

            if ($this->getStatus()!="DONE") {
                $todo++;
            } else { // $status = DONE
                if ($this->previousStatus!=null) {
                    $todo--;
                }
            }
            $this->getProject()->setTodo($todo);
        }
    }

    /**
     * @ORM\PreUpdate
     */
    public function updateTodoAfterUpdate()
    {
            $todo = $this->getProject()->getTodo();
            $this->getProject()->setTodo(24); // Pour tester

    }
}

Contrôleur (extrait):

/**
    * Show an item
    * @ParamConverter("project", options={"mapping": {"project_slug": "slug"}})
    * @ParamConverter("item", options={"mapping": {"item_slug": "slug"}})
    */
    public function showAction(Project $project, Item $item)
    {
        $request = $this->get('request');

        $form = $this->createForm(new ItemStatusType, $item);

        if ($request->getMethod()=='POST') {
            $form->bind($request);

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

                return $this->redirect($this->generateUrl('home_project', array('slug' => $project->getSlug())));
            }
        }

        return $this->render('BugTrackerProjectBundle:Items:show.html.twig', array('project' => $project, 'item' => $item, 'form' => $form->createView()));
    }

J'ai essayé de persister aussi project, de jouer sur les cascades, rien ne change, je ne vois pas où est l'erreur...

1 réponse


Maintenant ça fonctionne, mais lorsque le controleur fonctionne ainsi:

$em->persist($item);
$em->flush();
$em->persist($project);
$em->flush();

Ça fonctionne, mais je crois que normalement, il n'y aurait pas besoin de persister l'entité Project !