onetomany one many generate symfony orm doctrine2 one-to-one

one - Problema de Symfony2 Doctrine2 con relación opcional de uno a uno



symfony 4 onetomany (5)

Tengo un problema con Doctrine2 en Symfony2 y dos entidades relacionadas.

Existe una entidad de usuario que puede (no debe) tener una entidad de membrete a la que se hace referencia que contiene información como biografía, etc.

El usermeta es opcional porque el usuario es importado por otro sistema, mientras que usermeta se administra en mi aplicación.

Por supuesto, quiero guardar ambos juntos, de modo que al guardar un usuario debe crear o actualizar una usermeta-entity.

Ambos están unidos por una columna llamada aduserid (mismo nombre en ambas tablas).

Reconocí que si usermeta es una referencia opcional, el propietario en este caso debería ser usermeta, de lo contrario la doctrina carga al usuario y necesita la entidad usermeta, pero no siempre está ahí.

Tenga en cuenta los comentarios en Usuario-> setMeta ..

/** * User * * @ORM/Table(name="user") * @ORM/Entity */ class User { /** * @var Usermeta * @ORM/OneToOne(targetEntity="Usermeta", mappedBy="user", cascade={"persist"}) */ protected $meta; public function getMeta() { return $this->meta; } /** * * @param Usermeta $metaValue */ public function setMeta($metaValue) { // I''ve tried setting the join-column-value here // - but it''s not getting persisted // $metaValue->setAduserid($this->getAduserid()); // Then I''ve tried to set the user-object in Usermeta - but then // it seems like Doctrine wants to update Usermeta and searches // for ValId names aduserid (in BasicEntityPersister->_prepareUpdateData) // but only id is given - so not luck here // $metaValue->setUser($this); $this->meta = $metaValue; } /** * @var integer * * @ORM/Column(name="rowid", type="integer", nullable=false) * @ORM/Id * @ORM/GeneratedValue(strategy="IDENTITY") */ private $id; /** * Get rowid * * @return integer */ public function getId() { return $this->id; } /** * @var integer * * @ORM/Column(name="ADuserid", type="integer", nullable=false) */ private $aduserid; /** * Set aduserid * * @param integer $aduserid * @return User */ public function setAduserid($aduserid) { $this->aduserid = $aduserid; return $this; } /** * Get aduserid * * @return integer */ public function getAduserid() { return $this->aduserid; } // some mor fields.... }

Y la clase Usermeta:

/** * Usermeta * * @ORM/Table(name="userMeta") * @ORM/Entity */ class Usermeta { /** * @ORM/OneToOne(targetEntity="User", inversedBy="meta") * @ORM/JoinColumn(name="ADuserid", referencedColumnName="ADuserid") */ protected $user; public function getUser() { return $this->$user; } public function setUser($userObj) { $this->user = $userObj; } /** * @var integer * * @ORM/Column(name="id", type="integer", nullable=false) * @ORM/Id * @ORM/GeneratedValue(strategy="IDENTITY") */ private $id; /** * @var integer * * @ORM/Column(name="ADuserid", type="integer", nullable=false) */ private $aduserid; /** * Set aduserid * * @param integer $aduserid * @return User */ public function setAduserid($aduserid) { $this->aduserid = $aduserid; return $this; } /** * Get aduserid * * @return integer */ public function getAduserid() { return $this->aduserid; } }

el código del controlador se ve así:

... $userForm->bind($request); if($userForm->isValid()) { $em->persist($user); $em->flush(); } ...


El comentario de Zdenek Machek es casi correcto. Como puede ver en la documentación de Doctrine2, la opción anulable debe estar en la anotación de combinación ( @JoinColumn ), no en la asignación ( @OneToOne ).

@JoinColumn doc:

Esta anotación se usa en el contexto de las relaciones en los campos @ManyToOne, @OneToOne y en el contexto de @JoinTable anidado dentro de @ManyToMany. Esta anotación no es requerida. Si no se especifica, los atributos name y referencedColumnName se deducen de la tabla y los nombres de las claves principales.

Atributos requeridos:

nombre : nombre de columna que contiene el identificador de clave externa para esta relación. En el contexto de @JoinTable, especifica el nombre de la columna en la tabla de unión.

referenciadoColumnName : nombre del identificador de clave principal que se utiliza para unir esta relación.

Atributos opcionales:

unique : determina si esta relación es exclusiva entre las entidades afectadas y se debe aplicar de manera que esté en el nivel de restricción de la base de datos. El valor predeterminado es falso.

nullable: determina si se requiere la entidad relacionada, o si null es un estado permitido para la relación. El valor predeterminado es verdadero.

onDelete : Cascade Action (Nivel de base de datos)

onUpdate : Cascade Action (nivel de base de datos)

columnDefinition : fragmento de SQL DDL que se inicia después del nombre de la columna y especifica la definición de columna completa (¡no portátil!). Este atributo permite hacer uso de funciones avanzadas de RMDBS. El uso de este atributo en @JoinColumn es necesario si necesita definiciones de columnas ligeramente diferentes para unir columnas, por ejemplo, con respecto a los valores predeterminados NULL / NOT NULL. Sin embargo, de forma predeterminada, un atributo "columnDefinition" en @Column también establece la definición de columna de @ JoinColumn relacionada. Esto es necesario para que las claves externas funcionen.

http://doctrine-orm.readthedocs.org/en/latest/reference/annotations-reference.html#annref-joincolumn

@OneToOne doc:

La anotación @OneToOne funciona casi exactamente como @ManyToOne con una opción adicional que se puede especificar. Los valores predeterminados de configuración para @JoinColumn utilizando la tabla de entidad de destino y los nombres de columna de clave primaria se aplican también aquí.

Atributos requeridos:

targetEntity : FQCN de la entidad objetivo referenciada. Puede ser el nombre de clase no calificado si ambas clases están en el mismo espacio de nombres. IMPORTANTE: ¡Sin barras diagonales inversas!

Atributos opcionales:

cascada : Opción Cascade

fetch : uno de LAZY o EAGER

orphanRemoval : Boolean que especifica si Doctrine debe eliminar huérfanos, entidades OneToOne inversas que no están conectadas a ninguna instancia propietaria. El valor predeterminado es falso.

invertedBy : El atributo invertedBy designa el campo en la entidad que es el lado inverso de la relación.

http://doctrine-orm.readthedocs.org/en/latest/reference/annotations-reference.html#onetoone


Espero no molestar a nadie presentando esta respuesta tardía, pero así es como resolví este problema:

/** * @var Takeabyte/GripBundle/Entity/PDF * @ORM/OneToOne(targetEntity="Takeabyte/GripBundle/Entity/PDF", inversedBy="element", fetch="EAGER", orphanRemoval=true) */ protected $pdf = null;

Agregué = null; a la declaración de atributo. Espero que sea de ayuda para cualquiera que lea esto.


Está utilizando el tipo incorrecto de Relación para su problema.

Lo que quiere es unidireccional uno a uno desde Usermeta a User .

Una relación uno a uno bidireccional significaría lo siguiente:

  1. Un usuario DEBE tener un objeto Usermeta.
  2. Un objeto Usermeta DEBE tener un usuario.

En su caso, solo está tratando de requerir la segunda condición.

Esto significa que solo puedes hidratar al usuario de Usermeta y no al revés.

Lamentablemente, la doctrina no admite las relaciones cero o uno a muchos .


Leer mi vieja pregunta es bastante divertido ya que veo el problema a primera vista ahora ...

Cuando se trata de una solución, he pensado que esa doctrina solo puede manejar Id. Con el nombre "id", pero ... no está marcado como ID, falta la anotación Id y Doctrina no puede usar los campos para la columna de unión.

En segundo lugar, Zdenek Machek tenía razón: tiene que marcarse como nulo.


Obtuve el mensaje de error "spl_object_hash () espera que el parámetro 1 sea objeto, nulo dado en ..." al intentar lo mismo. Traté de definir una relación One to One bidireccional, mientras que el valor invertido podría ser null . Esto dio el mensaje de error. Quitar el lado inverso de la relación resolvió el problema. Es una lástima que las relaciones Zero or One to One no sean compatibles.