web-dev-qa-db-fra.com

Symfony2, Doctrine2 - force update - le tableau existe déjà sur une relation plusieurs à plusieurs

Après avoir créé avec succès TaskBundle avec une relation un-à-plusieurs entre catégorie et tâches, j'essaie maintenant de créer une nouvelle relation TaskBundle avec plusieurs-plusieurs. Je rencontre également un problème avec la case à cocher dans cette relation, mais ce n’est plus un problème principal (peut-être après avoir résolu le problème). J'ai supprimé toutes les tables, c'est-à-dire que TaskBundle utilise et essaie de créer une nouvelle, mais voici un problème (description en bas). 

Mon objet de tâche:

<?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 is 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 have to agree.")    
     */         
    protected $accepted;

    /**
     * @ORM\ManyToMany(targetEntity="Category", inversedBy="tasks")
     * @ORM\JoinTable(name="categories")                         
     */
    protected $category;

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

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

    /**
     * Set task
     *
     * @param string $task
     * @return Task
     */
    public function setTask($task)
    {
        $this->task = $task;

        return $this;
    }

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

    /**
     * Set dueDate
     *
     * @param \DateTime $dueDate
     * @return Task
     */
    public function setDueDate($dueDate)
    {
        $this->dueDate = $dueDate;

        return $this;
    }

    /**
     * Get dueDate
     *
     * @return \DateTime 
     */
    public function getDueDate()
    {
        return $this->dueDate;
    }

    /**
     * Add category
     *
     * @param \Acme\TaskBundle\Entity\Category $category
     * @return Task
     */
    public function addCategory(\Acme\TaskBundle\Entity\Category $category)
    {
        $this->category[] = $category;

        return $this;
    }

    /**
     * Remove category
     *
     * @param \Acme\TaskBundle\Entity\Category $category
     */
    public function removeCategory(\Acme\TaskBundle\Entity\Category $category)
    {
        $this->category->removeElement($category);
    }

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

et objet 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, unique=true)   
     * @Assert\NotNull(message="Categories cannot be empty", groups = {"adding"})                   
     */         
    protected $name;  

    /**
     * @ORM\ManyToMany(targetEntity="Task", mappedBy="category")
     */
    private $tasks;            


    public function __toString()
    {
        return strval($this->name);
    }
    /**
     * Constructor
     */
    public function __construct()
    {
        $this->tasks = new \Doctrine\Common\Collections\ArrayCollection();
    }

    /**
     * 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;
    }

    /**
     * Add tasks
     *
     * @param \Acme\TaskBundle\Entity\Task $tasks
     * @return Category
     */
    public function addTask(\Acme\TaskBundle\Entity\Task $tasks)
    {
        $this->tasks[] = $tasks;

        return $this;
    }

    /**
     * Remove tasks
     *
     * @param \Acme\TaskBundle\Entity\Task $tasks
     */
    public function removeTask(\Acme\TaskBundle\Entity\Task $tasks)
    {
        $this->tasks->removeElement($tasks);
    }

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

Donc, après avoir mis doctrine:schema:update --force, je vais obtenir une erreur: Table 'symfony.categories' already exists. J'ai essayé de supprimer tous les caches, mais le même problème. Une idée?

Il n'y a qu'un problème, si c'est en tant que relation m2m.

PS: Je cherchais ce problème chez Google, mais personne ne répond à ce problème. Il y avait seulement des questions, mais pas des réponses correctes, où se trouvait le problème et comment le résoudre.

20
Bc. Poklop

On dirait que vous avez déjà un tableau nommé "catégories" dans cette base de données. Supprimez cette ligne @ORM\JoinTable(name="categories") et essayez sans elle.

P.S. "Catégories" est vraiment un nom étrange pour rejoindre la table. Vous devriez probablement suivre certaines conventions et laisser la doctrine le nommer. Les noms communs pour les tables de jointure sont category_task ou category2task car ils sont plus explicites. Rien ça important, juste essayer de suggérer ce que je considère comme une bonne pratique.

15
Igor Pantović

Le fait est que la doctrine ne comprend pas comment votre table existante devrait être utilisée. Mais vous pouvez lui donner de l'aide.

Vous avez deux options:

  • Vous ne vous souciez pas de la table existante: simple, vous pouvez supprimer l'annotation @ORM\JoinTable(name="categories"), et doctrine va créer une autre table, etc.

  • Vous voulez conserver votre table existante, ce qui semble assez logique: vous devez être plus explicite dans votre annotation en ajoutant l'annotation @ORM\JoinColumn.

Voici un exemple:

class 

<?php
...
/**
 * @ORM\Entity
 * @ORM\Table(name="tasks") 
 */
class Task
{
    ...
    /**
     * @ORM\ManyToMany(targetEntity="Category", inversedBy="tasks")
     * @ORM\JoinTable(name="categories",
     *       joinColumns={@ORM\JoinColumn(name="category_id", referencedColumnName="id")},
     *       inverseJoinColumns={@ORM\JoinColumn(name="task_id", referencedColumnName="id")})                         
     */
    protected $category;
    ...
}

et objet Category

<?php
...    
/**
 * @ORM\Entity
 * @ORM\Table(name="categories") 
 */
class Category
{
    ...
    /**
     * @ORM\ManyToMany(targetEntity="Task", mappedBy="category")
     * @ORM\JoinTable(name="categories",
     *       joinColumns={@ORM\JoinColumn(name="task_id", referencedColumnName="id")},
     *       inverseJoinColumns={@ORM\JoinColumn(name="category_id", referencedColumnName="id")})
     */
    private $tasks;            
...

Ce faisant, vous pourrez garder votre table sans erreur de doctrine.

7
Ben Tazulev

Pour autant que je sache, mon correctif était un problème de distinction de casse avec les noms de table. Doctrine m'a laissé créer une table Users et une table users, mais mourrait ensuite lors de migrations: diff ou migrations: migrate. 

J'ai utilisé l'option -vvv pour obtenir plus de détails sur ce message d'erreur; il semble que l'erreur se produise lorsque Doctrine charge sa propre représentation interne du schéma de la base de données actuelle. Donc, si votre base de données actuelle a des noms de table que Doctrine ne comprend pas (comme deux tables identiques, insensibles à la casse), elle explose de cette manière.

On dirait que la plupart des réponses ci-dessus supposent que l'erreur se trouve dans votre code, mais dans mon cas, c'était dans la base de données.

3
willbradley

Je répare le même problème après avoir vérifié les autres entités de chaque groupe, soyez-en conscient.

0
Jean-Luc Barat

Essayez de tout déposer dans votre répertoire de proxy.

0
zinovyev

dans Symfony4.1 vous pouvez forcer la migration en utilisant la version de migration 

doctrine:migrations:execute <migration version>

ex

pour la migration version123456.php utiliser

doctrine:migrations:execute 123456
0
Sakhri Houssem

il y en a un autre qui utilise le nom de la table, vous pouvez le rechercher dans votre projet. Maby être démo, je pense que c'est .... désolé pour mon anglais chinois!

0
user5164320