doctrine2 - unidirectional - Opciones de Doctrine Cascade para OneToMany
findby doctrine (2)
Me está costando dar sentido a la explanation del manual de Doctrine sobre las operaciones en cascada y necesito que alguien me ayude a entender las opciones en términos de una relación simple de ManyToOne.
En mi aplicación, tengo una tabla / entidad llamada Article que tiene un campo de clave externa que hace referencia al campo ''id'' en una tabla / entidad llamada Topic.
Cuando creo un nuevo artículo, selecciono el tema en un menú desplegable. Esto inserta un número entero en el campo clave externa ''topic_id'' en la tabla Artículo.
Tengo la asociación $ topic configurada en la entidad Article de esta manera:
/**
* @ManyToOne(targetEntity="Topic")
* @JoinColumn(name="topic_id", referencedColumnName="id", nullable=false)
*/
private $topic;
La entidad Tema no tiene ninguna anotación recíproca con respecto a la entidad Artículo. A los temas no les importa qué Artículos los referencian y nada tiene que sucederle a un Tema cuando se elimina un Artículo que hace referencia al Tema.
Como no estoy especificando la operación en cascada en la entidad Artículo, Doctrine arroja un error cuando trato de crear un nuevo Artículo: "Se encontró una nueva entidad a través de una relación que no estaba configurada para continuar operaciones en cascada. Persistir explícitamente en la nueva entidad o configurar operaciones de persistencia en cascada en la relación ".
Entonces sé que necesito elegir una operación en cascada para incluir en la entidad Article, pero ¿cómo sé qué operación elegir en esta situación?
Al leer el manual de Doctrine, "separar" suena como la opción correcta. Pero investigar las preguntas similares de otros here y here me hace pensar que quiero usar "persistir" en su lugar.
¿Alguien puede ayudarme a entender qué significa "persistir", "eliminar", "fusionar" y "separar" en términos de una relación simple de ManyToOne como la que he descrito?
En la documentación de Doctrine2 " 9.6 Persistencia transitiva / Operaciones en cascada " hay algunos ejemplos de cómo debe configurar sus entidades para que cuando persista $ artículo, el $ tema también se mantenga. En tu caso, sugeriría esta anotación para la entidad del tema:
/**
* @OneToMany(targetEntity="Article", mappedBy="topic", cascade={"persist", "remove"})
*/
private $articles;
El inconveniente de esta solución es que debe incluir $ articles collection en la entidad Topic, pero puede dejarla en privado sin getter / setter.
Y como se mencionó en @kurt-krueckeberg, debe pasar la entidad del tema real al crear un nuevo artículo, es decir:
$topic = $em->getRepository(''Entity/Topic'')->find($id);
$article = new Article($topic);
$em->persist($article);
$em->flush();
// perhaps, in this case you don''t even need to configure cascade operations
¡Buena suerte!
Si tiene una asociación unidireccional @OneToMany, como la descrita en la sección 6.10 de la Referencia de Doctrina, lo más probable es que haya olvidado continuar el Tema antes de llamar al color. No establezca la clave primaria topic_id en Article. En su lugar, configure la instancia de Tema.
Por ejemplo, entidades de Artículo y Tema determinadas como estas:
<?php
namespace Entities;
/**
@Entity
@Table(name="articles")
*/
class Article {
/**
* @Id
* @Column(type="integer", name="article_id")
* @GeneratedValue
*/
protected $id;
/**
* @Column(type="text")
*/
protected $text;
/**
* @ManyToOne(targetEntity="Topic", inversedBy="articles")
* @JoinColumn(name="topic_id", referencedColumnName="topic_id")
*/
protected $topic;
public function __construct($text=null)
{
if (!is_null($text)) {
$this->text = $text;
}
}
public function setArticle($text)
{
$this->text = $text;
}
public function setTopic(Topic $t)
{
$this->topic = $t;
}
}
<?php
namespace Entities;
/**
@Entity
@Table(name="topics")
*/
class Topic {
/**
* @Id
* @Column(type="integer", name="topic_id")
* @GeneratedValue
*/
protected $id;
public function __construct() {}
public function getId() {return $this->id;}
}
Después de generar el esquema:
# doctrine orm:schema-tool:create
su código para persistir estas entidades se vería como algo así
//configuration omitted..
$em = /Doctrine/ORM/EntityManager::create($connectionOptions, $config);
$topic = new Entities/Topic();
$article1 = new Entities/Article("article 1");
$article2 = new Entities/Article("article 2");
$article1->setTopic($topic);
$article2->setTopic($topic);
$em->persist($article1);
$em->persist($article2);
$em->persist($topic);
try {
$em->flush();
} catch(Exception $e) {
$msg= $e->getMessage();
echo $msg . "<br />/n";
}
return;
Espero que esto ayude.