Solución:
- mappedBy tiene que ser especificado en el lado invertido de una asociación (bidireccional)
- invertedBy tiene que ser especificado en el lado dueño de una asociación (bidireccional)
de la documentación de la doctrina:
- ManyToOne es siempre el lado propietario de una asociación bidireccional.
- OneToMany es siempre el lado inverso de una asociación bidireccional.
- El lado propietario de una asociación OneToOne es la entidad con la tabla que contiene la clave externa.
Ver https://www.doctrine-project.org/projects/doctrine-orm/en/latest/reference/unitofwork-associations.html
Las respuestas anteriores no fueron suficientes para que yo entendiera lo que estaba pasando, así que después de ahondar más en ello, creo que tengo una forma de explicarlo que tendrá sentido para las personas que lucharon como yo para entender.
inversedBy y mappedBy son utilizados por el DOCTRINA INTERNA motor a reducir el número de consultas SQL tiene que ver con obtener la información que necesita. Para que quede claro si no agrega inversedBy o mappedBy, su código seguirá funcionando pero no optimizado.
Entonces, por ejemplo, mire las clases a continuación:
class Task
{
/**
* @var int
*
* @ORMColumn(name="id", type="integer")
* @ORMId
* @ORMGeneratedValue(strategy="AUTO")
*/
private $id;
/**
* @var string
*
* @ORMColumn(name="task", type="string", length=255)
*/
private $task;
/**
* @var DateTime
*
* @ORMColumn(name="dueDate", type="datetime")
*/
private $dueDate;
/**
* @ORMManyToOne(targetEntity="Category", inversedBy="tasks", cascade={"persist"})
* @ORMJoinColumn(name="category_id", referencedColumnName="id")
*/
protected $category;
}
class Category
{
/**
* @var int
*
* @ORMColumn(name="id", type="integer")
* @ORMId
* @ORMGeneratedValue(strategy="AUTO")
*/
private $id;
/**
* @var string
*
* @ORMColumn(name="name", type="string", length=255)
*/
private $name;
/**
* @ORMOneToMany(targetEntity="Task", mappedBy="category")
*/
protected $tasks;
}
Estas clases si tuviera que ejecutar el comando para generar el esquema (por ejemplo, bin/console doctrine:schema:update --force --dump-sql
) notará que la tabla Categoría no tiene una columna para las tareas. (esto se debe a que no tiene una anotación de columna)
Lo importante que hay que entender aquí es que las tareas variables solo están allí para que el motor de doctrina interno pueda usar la referencia que se encuentra arriba que dice su mappedBy Category. Ahora … no te confundas aquí como yo … La categoría NO se refiere al NOMBRE DE LA CLASE, se refiere a la propiedad de la clase Task llamada ‘categoría $ protegida’.
Del mismo modo, en la clase Tasks, la propiedad $ categoría menciona que es inversedBy = “tasks”, observe que es plural, este NO ES EL PLURAL DEL NOMBRE DE LA CLASE, pero solo porque la propiedad se llama ‘tareas $ protegidas’ en la clase Categoría.
Una vez que comprenda esto, será muy fácil comprender qué están haciendo inversedBy y mappedBy y cómo usarlos en esta situación.
El lado que hace referencia a la clave externa como ‘tareas’ en mi ejemplo siempre obtiene el atributo inversedBy porque necesita saber qué clase (a través del comando targetEntity) y qué variable (inversedBy =) en esa clase para ‘trabajar hacia atrás’ para hablar y obtener la información de la categoría. Una forma fácil de recordar esto es que la clase que tendría el Foreignkey_id es la que necesita tener invertedBy.
Donde, al igual que con la categoría, y su propiedad $ tasks (que no está en la tabla, recuerde, solo una parte de la clase para fines de optimización) está asignada por ‘tareas’, esto crea la relación oficialmente entre las dos entidades para que la doctrina pueda ahora de forma segura utilice sentencias JOIN SQL en lugar de dos sentencias SELECT independientes. Sin mappedBy, el motor de doctrina no sabría de la declaración JOIN que creará qué variable en la clase ‘Tarea’ para poner la información de la categoría.
Espero que esto lo explique un poco mejor.
En la relación bidireccional tiene un lado propietario y un lado inverso
mappedBy : poner en el lado inverso de una relación bidireccional Para referirse a su lado propietario
invertedBy : poner en El lado propietario de una relación bidireccional Para hacer referencia a su lado inverso
Y
mappedBy atributo utilizado con la declaración de mapeo OneToOne, OneToMany o ManyToMany.
invertedBy atributo utilizado con la declaración de mapeo OneToOne, ManyToOne o ManyToMany.
Aviso : El lado propietario de una relación bidireccional el lado que contiene la clave externa.
Hay dos referencias sobre inversedBy y mappedBy en la documentación de Doctrine: primer enlace, segundo enlace