Doctrines options en Cascade pour OneToMany

j'ai du mal à donner un sens à l'explication du manuel de Doctrine des opérations en cascade et j'ai besoin de quelqu'un pour m'aider à comprendre les options en termes d'une simple relation ManyToOne.

dans mon application, j'ai une table/entité nommée Article qui a un champ 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. Ceci insère un entier dans le champ 'topic_id' de la clé étrangère dans la table Article.

j'ai l'association $ topic établie dans l'entité D'Article comme ceci:

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

l'entité du sujet n'a pas d'annotation réciproque concernant l'entité de L'Article. Les sujets ne se soucient pas ce que les Articles de référence eux et rien n'a besoin d'arriver à un sujet quand un Article qui renvoie le sujet est supprimé.

parce que je ne suis pas en spécifiant l'opération en cascade dans l'entité de L'Article, La Doctrine envoie une erreur quand j'essaie de créer un nouvel Article: "une nouvelle entité a été trouvée grâce à une relation qui n'a pas été configuré pour les opérations en cascade persist. Persistent explicitement la nouvelle entité ou les opérations de configuration en cascade persistent sur la relation."

donc je sais que je dois choisir une opération en cascade à inclure dans l'entité de L'Article, mais comment puis-je savoir quelle opération à choisir dans cette situation?

D'après le manuel de Doctrine, "détacher" semble être la bonne option. Mais faire des recherches sur les questions similaires des autres ici et ici 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" signifie en termes d'une simple relation ManyToOne comme celle que j'ai décrite?

37
demandé sur Community 2011-10-10 10:41:00

2 réponses

dans la documentation Doctrine2 " 9.6. La persistance Transitive / Cascade d'Opérations " il y a quelques exemples de la façon dont vous devriez configurer votre entités de sorte que lorsque vous persistez $article, $sujet serait également persisté. Dans votre cas, je suggérerais cette annotation pour L'entité du sujet:

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

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

et comme @kurt-krueckeberg l'a mentionné, vous devez passer la véritable entité du sujet lors de la création d'un 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!

27
répondu Sergiy Sokolenko 2014-09-22 11:53:41

si vous avez une association unidirectionnelle @OneToMany, comme celle décrite dans la section 6.10 de la référence de Doctrine, alors très probablement vous avez oublié de persister le sujet avant d'appeler flush. Ne définissez pas la clé primaire topic_id dans Article. Au lieu de cela, définissez l'instance du sujet.

par exemple, étant donné l'article et les entités de 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 pour persister ces entités ressemblerait à quelque chose de ce

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

0
répondu Kurt Krueckeberg 2011-12-11 16:29:09