上面的答案不足以让我理解发生了什么,所以在深入研究之后,我认为我有一种解释它的方法,这对于像我一样努力理解的人来说是有意义的。
INTERNAL DOCTRINE引擎使用 inversedBy 和 mappedBy来减少为获取所需信息而必须执行的 SQL 查询的数量。要清楚,如果您不添加 inversedBy 或 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
),您会注意到 Category 表上没有用于任务的列。(这是因为它上面没有列注释)
这里要理解的重要一点是变量 tasks 仅存在于其中,因此内部学说引擎可以使用上面的引用,它表示它的 mappedBy 类别。现在...不要像我一样在这里混淆... Category 不是指类名,它指的是 Task 类上称为“受保护的 $category”的属性。
同样,在 Tasks 类上,属性 $category 提到它是 inversedBy="tasks",注意这是复数,这不是类名的复数,而只是因为该属性在 Category 中被称为“受保护的 $tasks”班级。
一旦你理解了这一点,就很容易理解 inversedBy 和 mappedBy 在做什么以及如何在这种情况下使用它们。
在我的示例中,引用外键(如“任务”)的一侧总是获得 inversedBy 属性,因为它需要知道该类上的哪个类(通过 targetEntity 命令)和哪个变量(inversedBy=)才能“向后工作”,以便说话并从中获取类别信息。记住这一点的一种简单方法是,将具有 foreignkey_id 的类是需要具有 inversedBy 的类。
与 category 一样,它的 $tasks 属性(记住,它只是类的一部分用于优化目的)是 MappedBy 'tasks',这在两个实体之间正式创建了关系,因此学说现在可以安全地使用 JOIN SQL 语句而不是两个单独的 SELECT 语句。如果没有 mappedBy,原则引擎不会从 JOIN 语句中知道它将在“Task”类中创建什么变量来放置类别信息。
希望这能更好地解释它。