2011-10-10 6 views
36

Ho difficoltà a dare un senso al manuale explanation del manuale di Doctrine delle operazioni in cascata e ho bisogno di qualcuno che mi aiuti a comprendere le opzioni in termini di una semplice relazione ManyToOne.Opzioni di Doctrine Cascade per OneToMany

Nella mia applicazione, ho una tabella/entità di nome Articolo che ha un campo chiave esterna che fa riferimento al campo "id" in una tabella/entità denominata Argomento.

Quando creo un nuovo articolo, seleziono l'argomento da un menu a discesa. Questo inserisce un intero nel campo chiave esterna 'topic_id' nella tabella Articolo.

ho l'associazione argomento $ istituito nell'articolo soggetto come questo:

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

L'entità argomento non ha alcuna annotazione alternativo per quanto riguarda l'articolo entità. Gli argomenti non si preoccupano di ciò che gli articoli fanno riferimento a loro e nulla deve accadere a un argomento quando un articolo che fa riferimento all'argomento viene eliminato.

Poiché non sto specificando l'operazione a cascata nell'entità Articolo, Doctrine genera un errore quando provo a creare un nuovo articolo: "È stata trovata una nuova entità tramite una relazione che non è stata configurata per le operazioni persistenti in cascata. persiste la nuova entità o configura le operazioni persistenti a cascata sulla relazione. "

Quindi so che è necessario scegliere un'operazione a cascata da includere nell'entità Articolo, ma come faccio a sapere quale operazione scegliere in questa situazione?

Dalla lettura del manuale di Doctrine, "staccare" suona come l'opzione giusta. Ma la ricerca delle domande simili degli altri here e here mi fa pensare che preferirei usare "persist".

Qualcuno può aiutarmi a capire che cosa "persist", "rimuovere", "unire" e "staccare" significano in termini di una semplice relazione ManyToOne come quella che ho descritto?

+6

+1 per la buona domanda. Spero che qualcuno risponda presto, mi piacerebbe saperne di più sull'opzione a cascata. Al momento mancano libri o documentazione su Doctrine2. Il collegamento – gremo

risposta

27

Nella documentazione di Doctrine2 "9.6. Transitive persistence/Cascade Operations" ci sono alcuni esempi di come si dovrebbero configurare le proprie entità in modo tale che quando si mantiene un articolo $, anche l'argomento $ venga mantenuto. Nel tuo caso io suggerirei questa annotazione per l'entità Topic:

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

Lo svantaggio di questa soluzione è che si deve includere $ articoli collezione all'argomento entità, ma si può lasciare privata senza getter/setter.

e come detto @ kurt-krueckeberg, è necessario passare l'entità vera discussione durante la creazione di un nuovo articolo, cioè .:

$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 

Buona fortuna!

+0

è morto. puoi trovarne uno nuovo? – ferdynator

+0

@ferdynator Ho aggiornato il collegamento, grazie per l'avviso. – Serg

0

Se si dispone di un'associazione unidirezionale @OneToMany, come quella descritta nella sezione 6.10 di Doctrine Reference, molto probabilmente si è dimenticato di persistere l'Argomento prima di chiamare flush. Non impostare la chiave primaria topic_id nell'articolo. Invece imposta l'istanza Topic.

Per esempio, dato articolo e soggetto entità come questi:

<?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;} 
} 

Dopo aver generato lo schema:

# doctrine orm:schema-tool:create 

il codice a persistere queste entità sarebbe simile a qualcosa di questo

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

Spero che questo aiuti.