Symfony2, Doctrine2 - force update - таблица уже существует относительно отношения "многие ко многим"
После того, как я успешно создал TaskBundle с отношением "один ко многим" между категорией и задачами, теперь я пытаюсь создать новый элемент TaskBundle с отношением Many-to-Many. Я также сталкиваюсь с проблемой проверки флажка в этом отношении, но теперь это не основная проблема (возможно, после ее решения). Я удалил все таблицы, которые TaskBundle использует и пытается создать новый, но вот проблема (описание внизу).
Объект My Task:
<?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;
}
}
и объект 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: Я искал эту проблему в Google, но никто не отвечает на эту проблему. Были только вопросы, но не правильные ответы, где проблема и как ее решить.
Ответы
Ответ 1
Похоже, у вас уже есть таблица с именем "категории" в этой базе данных. Удалите эту строку @ORM\JoinTable(name="categories")
и попробуйте без нее.
P.S. "Категории" действительно странное имя для таблицы join. Вероятно, вы должны следовать некоторым соглашениям и позволить доктрине называть это. Общие имена для таблиц объединений category_task
или category2task
, поскольку они более понятны. Ничего , что важно, просто пытаюсь предложить, что я считаю хорошей практикой.
Ответ 2
Дело в том, что доктрина не понимает, как использовать существующую таблицу. Но вы можете помочь ему.
У вас есть два варианта:
-
Вы не заботитесь о существующей таблице: просто, вы можете удалить аннотацию @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;
...
}
и объект 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;
...
Таким образом, вы сможете сохранить таблицу без какой-либо ошибки доктрины.
Ответ 3
Мое исправление для этого, насколько я могу судить, было вопросом чувствительности к регистру с именами таблиц. Doctrine позволил мне создать таблицу Users
и Users
, но потом умрет при миграции: diff или migrations: migrate.
Я использовал опцию -vvv, чтобы получить более подробную информацию об этом сообщении об ошибке; кажется, что ошибка возникает, когда Doctrine загружает собственное внутреннее представление текущей схемы базы данных. Поэтому, если ваша текущая база данных имеет имена таблиц, которые Doctrine не понимает (например, две таблицы, которые идентичны, не чувствительны к регистру), тогда она взорвется таким образом.
Похоже, что большинство ответов выше предполагают, что ошибка указана в вашем коде, но в моем случае она была в базе данных.
Ответ 4
есть другое имя таблицы, вы можете искать его в своем проекте. Маби будь демо, я думаю, это...
извините за мой китайский английский!
Ответ 5
Попробуйте отбросить все содержимое каталога прокси.
Ответ 6
Я исправляю такую же проблему после проверки других объектов в каждом пакете, помните об этом.
Ответ 7
в Symfony4.1
вы можете форсировать миграцию, используя версию миграции
doctrine:migrations:execute <migration version>
бывший
для миграции использовать version123456.php
doctrine:migrations:execute 123456
Ответ 8
Я получил эту ошибку, когда 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;