2011-10-10 26 views
36

Tengo dificultades para comprender las operaciones en cascada del manual de Doctrine explanation y necesito que alguien me ayude a comprender las opciones en términos de una relación simple de ManyToOne.Opciones de Doctrine Cascade para OneToMany

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.

que tienen el tema $ asociación creada en la entidad artículo así:

/** 
* @ManyToOne(targetEntity="Topic") 
* @JoinColumn(name="topic_id", referencedColumnName="id", nullable=false) 
*/ 
private $topic; 

La entidad tema no tiene ninguna anotación de vaivén 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 intento 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 la nueva entidad o configurar las operaciones de persistencia en cascada en la relación ".

Así que sé que necesito elegir una operación en cascada para incluir en la entidad Artículo, 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" significa en términos de una relación simple de ManyToOne como la que he descrito?

+6

+1 para la buena pregunta. Espero que alguien lo responda pronto, me gustaría obtener más información sobre la opción de cascada. Faltan libros o documentación sobre Doctrine2 en este momento. – gremo

Respuesta

27

En la documentación de Doctrine2 "9.6. Transitive persistence/Cascade Operations" hay algunos ejemplos de cómo debe configurar sus entidades para que cuando persista $ artículo, el $ tema también se mantenga. En su caso me gustaría sugerir esta anotación de entidad Tema:

/** 
* @OneToMany(targetEntity="Article", mappedBy="topic", cascade={"persist", "remove"}) 
*/ 
private $articles; 

El inconveniente de esta solución es que usted tiene que incluir la recolección de artículos a $ Tema entidad, pero se puede dejar privada sin captador/definidor.

y como se mencionó @ Kurt-Krueckeberg, debe pasar la entidad real Tema al crear 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!

+0

enlace está muerto. puedes encontrar uno nuevo? – ferdynator

+0

@ferdynator He actualizado el enlace, gracias por avisarme. – Serg

0

Si tiene una asociación unidireccional @OneToMany, como la descrita en la sección 6.10 de la Referencia de Doctrina, entonces es muy probable 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, dados artículo y Tema entidades como éstas:

<?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 de persistir estas entidades se vería como algo tan

//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.

Cuestiones relacionadas