Приведенных выше ответов было недостаточно, чтобы понять, что происходит, поэтому, углубившись в это подробнее, я думаю, что у меня есть способ объяснить это, что будет иметь смысл для людей, которые боролись, как и я, чтобы понять.
InversedBy и mappedBy используются механизмом ВНУТРЕННЕЙ ДОКТРИНЫ, чтобы уменьшить количество SQL-запросов, которые он должен выполнять для получения необходимой информации. Чтобы прояснить ситуацию, если вы не добавите инвертированныйBy или mappedBy, ваш код все равно будет работать, но не будет оптимизирован .
Так, например, посмотрите на классы ниже:
class Task
{
/**
* @var int
*
* @ORM\Column(name="id", type="integer")
* @ORM\Id
* @ORM\GeneratedValue(strategy="AUTO")
*/
private $id;
/**
* @var string
*
* @ORM\Column(name="task", type="string", length=255)
*/
private $task;
/**
* @var \DateTime
*
* @ORM\Column(name="dueDate", type="datetime")
*/
private $dueDate;
/**
* @ORM\ManyToOne(targetEntity="Category", inversedBy="tasks", cascade={"persist"})
* @ORM\JoinColumn(name="category_id", referencedColumnName="id")
*/
protected $category;
}
class Category
{
/**
* @var int
*
* @ORM\Column(name="id", type="integer")
* @ORM\Id
* @ORM\GeneratedValue(strategy="AUTO")
*/
private $id;
/**
* @var string
*
* @ORM\Column(name="name", type="string", length=255)
*/
private $name;
/**
* @ORM\OneToMany(targetEntity="Task", mappedBy="category")
*/
protected $tasks;
}
Эти классы, если вы должны запустить команду для генерации схемы (например bin/console doctrine:schema:update --force --dump-sql
), вы заметите, что в таблице категорий нет столбца для задач. (это потому, что на нем нет аннотации столбца)
Здесь важно понимать, что переменные задачи существуют только для того, чтобы внутренний механизм доктрины мог использовать ссылку над ним, в которой указано его mappedBy Category. Теперь ... не путайте здесь, как я ... Категория НЕ относится к ИМЕНИ КЛАССА , это относится к свойству класса Task под названием «protected $ category».
Аналогично, в классе Tasks свойство $ category упоминает, что оно инвертированоBy = "tasks", обратите внимание, что это множественное число, это НЕ МНОЖЕСТВЕННОЕ ЧИСЛО ИМЕНИ КЛАССА , а только потому, что свойство называется 'protected $ tasks' в Категории класс.
Как только вы это поймете, станет очень легко понять, что делают reverseBy и mappedBy и как их использовать в этой ситуации.
Сторона, которая ссылается на внешний ключ, например `` задачи '' в моем примере, всегда получает атрибут инвертированного типа, потому что ей нужно знать, какой класс (с помощью команды targetEntity) и какая переменная (инверседби =) в этом классе будет `` работать в обратном направлении '', чтобы говорить и получать информацию о категории от. Легкий способ запомнить это: класс, который будет иметь foreignkey_id, - это тот, который должен иметь инверсию.
Если, как и в случае с категорией, и ее свойство $ tasks (которого нет в таблице, помните, это только часть класса для целей оптимизации) является MappedBy 'tasks', это создает официальную связь между двумя объектами, так что теперь доктрина может безопасно используйте операторы JOIN SQL вместо двух отдельных операторов SELECT. Без mappedBy механизм доктрины не узнает из оператора JOIN, какую переменную в классе «Задача» создаст, чтобы поместить информацию о категории.
Надеюсь, это немного лучше объясняет.