Варианты каскада доктрин для OneToMany - PullRequest
38 голосов
/ 10 октября 2011

Мне трудно разобраться в объяснении каскадных операций руководства Doctrine, и мне нужен кто-то, чтобы помочь мне понять варианты с точки зрения простых отношений ManyToOne.

В моем приложении у меня есть таблица / сущность с именем Article, которая имеет поле внешнего ключа, ссылающееся на поле 'id' в таблице / сущности с именем Topic.

Когда я создаю новую статью, я выбираю тему из выпадающего меню. Это вставит целое число в поле внешнего ключа topic_id в таблице Article.

У меня установлена ​​ассоциация $ topic в сущности Article следующим образом:

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

Субъект Topic не имеет ответной аннотации относительно сущности Article. Темам не важно, какие статьи ссылаются на них, и с темой ничего не должно случиться, когда удаляется статья, ссылающаяся на тему.

Поскольку я не указываю каскадную операцию в сущности Article, Doctrine выдает ошибку, когда пытаюсь создать новую Article: «В связи, которая не была настроена для каскадных операций persist, была обнаружена новая сущность. новый объект или настроить каскадные постоянные операции над отношениями. "

Итак, я знаю, что мне нужно выбрать каскадную операцию для включения в сущность Article, но как мне узнать, какую операцию выбрать в этой ситуации?

Из прочтения руководства по Доктрине «отсоединение» звучит как правильный вариант. Но изучение подобных вопросов других людей здесь и здесь заставляет меня думать, что я хочу использовать вместо этого "persist".

Может ли кто-нибудь помочь мне понять, что означают слова "сохраняться", "удалить", "объединить" и "отделить" в терминах простых отношений ManyToOne, подобных описанным мной?

Ответы [ 2 ]

28 голосов
/ 23 июня 2012

В документации Doctrine2 " 9.6. Транзитивное постоянство / каскадные операции " есть несколько примеров того, как вы должны сконфигурировать свои сущности, чтобы при сохранении $ article, тема $ также сохранялась.В вашем случае я бы предложил эту аннотацию для сущности Topic:

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

Недостаток этого решения заключается в том, что вам необходимо включить коллекцию $ article в сущность Topic, но вы можете оставить ее закрытой без получения / установки / установки.

И, как упомянул @ kurt-krueckeberg, вы должны передать реальную сущность Topic при создании новой статьи, а именно:

$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

Удачи!

0 голосов
/ 11 декабря 2011

Если у вас есть однонаправленная ассоциация @OneToMany, как описано в разделе 6.10 Справочника по доктрине, то, скорее всего, вы забыли сохранить тему до вызова flush. Не устанавливайте первичный ключ topic_id в статье. Вместо этого установите экземпляр темы.

Например, для заданных объектов Article и Topic, подобных этим:

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

После создания схемы:

# doctrine orm:schema-tool:create

ваш код для сохранения этих сущностей будет выглядеть примерно так

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

Надеюсь, это поможет.

...