2011-10-10 5 views
36

J'ai du mal à comprendre les opérations en cascade du manuel Doctrine explanation et j'ai besoin de quelqu'un pour m'aider à comprendre les options en termes d'une simple relation ManyToOne.Doctrine Cascade Options pour OneToMany

Dans mon application, j'ai une table/entité nommée Article qui a un champ de clé étrangère référençant le champ 'id' dans une table/entité nommée Sujet. Lorsque je crée un nouvel article, je sélectionne le sujet dans un menu déroulant.

Cela insère un entier dans le champ de clé étrangère 'topic_id' dans la table Article.

J'ai l'association sujet de $ mis en place dans l'entité de l'article comme celui-ci:

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

L'entité sujet n'a pas d'annotation alternative concernant l'entité de l'article. Les sujets se fichent de ce que les Articles les référencent et rien ne doit arriver à un Sujet lorsqu'un article référençant le Sujet est supprimé. Comme je ne spécifie pas l'opération en cascade dans l'entité Article, Doctrine génère une erreur lorsque j'essaie de créer un nouvel article: "Une nouvelle entité a été trouvée via une relation qui n'était pas configurée pour mettre en cascade les opérations de persistance. persiste la nouvelle entité ou configure les opérations de persistance en cascade sur la relation. " Donc, je sais que je dois choisir une opération en cascade à inclure dans l'entité article, mais comment puis-je savoir quelle opération choisir dans cette situation? A la lecture du manuel de Doctrine, "detach" sonne comme la bonne option. Mais la recherche des questions similaires des autres here et here me fait penser que je veux utiliser "persist" à la place. Est-ce que quelqu'un peut m'aider à comprendre ce que «persister», «supprimer», «fusionner» et «détacher» signifient en termes d'une simple relation ManyToOne comme celle que j'ai décrite?

+6

+1 pour la bonne question. J'espère que quelqu'un y répondra bientôt, j'aimerais en savoir plus sur l'option cascade. Il y a un manque de livres ou de documentation sur Doctrine2 pour le moment. – gremo

Répondre

27

Dans la documentation Doctrine2 "9.6. Transitive persistence/Cascade Operations", il existe quelques exemples de la façon dont vous devez configurer vos entités de sorte que lorsque vous persistez à $ article, le sujet $ soit également conservé. Dans votre cas, je vous suggère cette annotation pour l'entité Sujet:

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

L'inconvénient de cette solution est que vous devez inclure la collecte des articles $ à l'entité du sujet, mais vous pouvez laisser privé sans getter/setter.

Et comme @ kurt-Krueckeberg mentionné, vous devez passer l'entité réelle du sujet lors de la création nouvel article, i.e. .:

$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 

Bonne chance!

+0

le lien est mort. pouvez-vous en trouver un nouveau? – ferdynator

+0

@ferdynator J'ai mis à jour le lien, merci de m'avertir. – Serg

0

Si vous avez une association unidirectionnelle @OneToMany, comme celle décrite dans la section 6.10 de la Référence de la doctrine, vous avez probablement oublié de conserver le sujet avant d'appeler le vidage. Ne définissez pas la clé primaire topic_id dans Article. Au lieu de cela, définissez l'instance du sujet.

Par exemple, avec des entités de l'article et sujet comme ceux-ci:

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

Après avoir généré le schéma:

# doctrine orm:schema-tool:create 

votre code à persister ces entités ressemblerait à quelque chose cette

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

J'espère que cela aide.

Questions connexes