Symfony2,学说2 - 力更新 - 表已经存在于多对多关系上


Symfony2, Doctrine2 - force update - table already exists on many-to-many relation

在我成功创建了类别和任务之间具有一对多关系的任务捆绑包后,现在我正在尝试创建一个具有多对多关系的新任务捆绑包。我在这种关系中选中复选框时也遇到了问题,但现在这不是主要问题(也许在解决这个问题之后)。我删除了所有表,这是 TaskBundle 使用并尝试创建一个新表,但这是问题(底部的描述)。

我的任务对象:

<?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;
    }
}

和类别对象

<?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;
    }
}

所以,在我放doctrine:schema:update --force之后,我会得到错误:Table 'symfony.categories' already exists。我试图删除所有缓存,但同样的问题。知道吗?

只有问题,如果它是m2m关系。

PS:我在谷歌寻找这个问题,但没有人回答这个问题。只有问题,但没有正确的答案,问题在哪里以及如何解决它。

看起来该数据库中已经有名为"categories"的表。@ORM'JoinTable(name="categories")删除此行并尝试不使用它。

附言"类别"对于连接表来说确实是一个奇怪的名称。你可能应该遵循一些惯例,让教义来命名它。联接表的常用名称是category_taskcategory2task,因为它们更不言自明。没什么重要的,只是试图提出我认为的良好做法。

问题是该学说不了解应如何使用现有表。但你可以给他一些帮助。

您有两个选择:

  • 你不关心现有的表:简单,你可以删除@ORM'JoinTable(name="categories")注释,教义会创建一个其他表等。

  • 你想保留你现有的表,这听起来很合乎逻辑:你必须通过添加@ORM'JoinColumn注释来更明确

  • 地说明。

下面是一个示例:

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;
    ...
}

和类别对象

<?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;            
...

这样做,您将能够保持您的桌子而没有任何教义错误。

据我所知,我的解决方法是表名的区分大小写问题。教义让我创建一个Users和一个users表,但后来会死在迁移:diff 或迁移:迁移。

我使用 -vvv 选项来获取有关此错误消息的更多详细信息;似乎当 Doctrine 加载当前数据库架构的自己的内部表示时,就会发生错误。因此,如果您当前的数据库具有 Doctrine 无法理解的表名(例如两个相同的表,不区分大小写),那么它将以这种方式爆炸。

似乎上面的大多数答案都假设错误在您的代码中,但就我而言,它出现在数据库中。

我收到此错误,2 个针对同一实体的 ManyToMany(以下示例中的用户)。

若要创建表名原则,请使用实体和目标实体名称。

所以在我的情况下,它试图创建两次表thread_user

要调试它很容易。只需使用"@ORM''JoinTable"注释并指定表名称。

这是一个工作示例。

/**
 * @ORM'ManyToMany(targetEntity="App'Entity'User")
 * @ORM'JoinTable(name="thread_participant")
 */
private $participants;
/**
 * @ORM'ManyToMany(targetEntity="App'Entity'User")
 * @ORM'JoinTable(name="thread_recipient")
 */
private $recipients;
还有

另一个使用表名,你可以在项目中搜索。马比是演示,我认为它...对不起我的中文英语!

尝试将所有内容都放在代理目录中。

我在检查每个捆绑包上的其他实体后修复了相同的问题,请注意这一点。

Symfony4.1中,您可以使用迁移版本强制迁移

doctrine:migrations:execute <migration version>

前任

用于迁移version123456.php使用

doctrine:migrations:execute 123456