2010-07-25 3 views
9

Przeczytałem oficjalną dokumentację i mnóstwo wątków, ale wciąż nie znajduję rozwiązania dla mojej sytuacji. Mój przypadek jest bardzo prosty. Mam 2 podmioty: komentarze i słowa kluczowe dla nich. Jeden komentarz może zawierać wiele słów kluczowych, ale każde słowo kluczowe ma tylko jeden komentarz. Słowa kluczowe nie są unikalne w tabeli słów kluczowych. Postanowiłem więc, że jest to relacja jeden do wielu. Struktura Stoły są po prostu jak następuje:Problem zrozumienia mapowania relacji w doktrynie 2

słowa kluczowe

id   int(11) 
comment_id int(11) 
text  varchar(30) 

komentarze

id  int(11) 
text text 

Oto jak je odwzorowany:


/** 
* @Entity 
* @Table(name="comments") 
**/ 
class Comments 
{ 
    /** @Id @Column(type="integer") */ 
    private $id; 
    /** @Column(type="text") */ 
    private $text; 

    /** 
    * @OneToMany(targetEntity="keywords", mappedBy="comment_id") 
    */ 
    private $keywords; 

    public function getText(){return $this->text;} 
    public function getId(){return $this->id;} 
    public function getKeywords(){return $this->keywords;} 
} 
/** 
* @Entity 
* @Table(name="keywords") 
*/ 

class Keywords 
{ 
    /** @Id @Column(type="integer") */ 
    private $id; 

    private $text; 

    public function getText(){return $this->text;} 
    public function getId(){return $this->id;} 
} 
 

i jak stosując to tak:


$comments = $this->em->getRepository('comments')->findAll(); 
foreach($comments as $comment){ 
    foreach($comment->getKeywords() as $keyword){ 
     $keyword->getText(); 
    } 
}

i got to błędy:

 
Notice: Undefined index: comment_id in C:\web_includes\doctrine\ORM\Persisters\BasicEntityPersister.php on line 1096 
Notice: Trying to get property of non-object in C:\web_includes\doctrine\ORM\Persisters\BasicEntityPersister.php on line 1098 
Warning: Invalid argument supplied for foreach() in C:\web_includes\doctrine\ORM\Persisters\BasicEntityPersister.php on line 1098 
Notice: Undefined index: comment_id in C:\web_includes\doctrine\ORM\PersistentCollection.php on line 168 
Fatal error: Call to a member function setValue() on a non-object in C:\web_includes\doctrine\ORM\PersistentCollection.php on line 169 
Co jest nie tak? gdzie powinien zdefiniować comment_id? Czy moje mapowanie jest poprawne? Naprawdę utknąłem i potrzebuję pomocy, więc proszę, wszelkie rady są bardzo mile widziane.

+0

co o 'comment_id'? jak ustawić relację między komentarzami i słowami kluczowymi? – Sadat

+0

comment_id to pole w bazie danych w tabeli słów kluczowych o identyfikatorze komentarza, do którego należy to słowo kluczowe. Przypuszczam, że doktryna użyje go przy wyborze słów kluczowych do komentarzy. relacja jest taka: OneToMany (targetEntity = "słowa kluczowe", mappedBy = "comment_id") czy to prawda? – SET

Odpowiedz

13

Atrybut mappedBy nie mówi nic o nazwie klucza obcego, do czego służy adnotacja "@JoinColumn". Prawidłowe odwzorowanie dla tego scenariusza byłoby:

/** 
* @Entity 
* @Table(name="comments") 
**/ 
class Comments 
{ 
    /** @Id @Column(type="integer") */ 
    private $id; 
    /** @Column(type="text") */ 
    private $text; 

    /** 
    * @OneToMany(targetEntity="keywords", mappedBy="comment") 
    */ 
    private $keywords; 

    public function getText(){return $this->text;} 
    public function getId(){return $this->id;} 
    public function getKeywords(){return $this->keywords;} 
} 

/** 
* @Entity 
* @Table(name="keywords") 
*/ 
class Keywords 
{ 
    /** @Id @Column(type="integer") */ 
    private $id; 

    /** 
    * @ManyToOne(targetEntity="Comments", inversedBy="keywords") 
    */ 
    private $comment; 

    /** 
    * @Column(type="text") */ 
    private $text; 

    public function getText(){return $this->text;} 
    public function getId(){return $this->id;} 
} 

Używanie schematu Narzędzie generuje SQL co równa schematu:

CREATE TABLE comments (id INT NOT NULL, text LONGTEXT NOT NULL, PRIMARY KEY(id)) ENGINE = InnoDB; 
CREATE TABLE keywords (id INT NOT NULL, comment_id INT DEFAULT NULL, text LONGTEXT NOT NULL, PRIMARY KEY(id)) ENGINE = InnoDB; 
ALTER TABLE keywords ADD FOREIGN KEY (comment_id) REFERENCES comments(id); 

dwa problemy w swoim mapowania:

  1. trzeba zrozumieć różnicę między posiadaniem a odwrotnością. Posiadanie jedno-do-wielu relacji jednokierunkowych wymaga trzeciej tabeli sprzężenia. Jednak z dwukierunkową relacją, jak w moim mapowaniu z właściwością sideing :: Keyword :: $ comment, to działa.
  2. "mappedBy" odnosi się do właściwości na innej targetEntity, która jest "drugą stroną tego powiązania". InversedBy ma w pewnym sensie to samo znaczenie, tyle że odwrócony jest zawsze określony po stronie posiadania, odwzorowany na odwrotnej stronie.

Wszystko to brzmi bardzo skomplikowanie, ale jest bardzo skutecznym sposobem z punktu widzenia technologii ORM, ponieważ pozwala na aktualizację skojarzeń z najmniejszą liczbą wymaganych instrukcji SQL UPDATE. Zobacz docs dotyczące Inverse/robót Owning

http://www.doctrine-project.org/projects/orm/2.0/docs/reference/association-mapping/en#owning-side-and-inverse-side

+0

TO NAPRAWDĘ DZIAŁA! wielkie dzięki. Ale muszę zapytać, jaka jest różnica między relacjami jednokierunkowymi a dwukierunkowymi.Ponadto, jaki podmiot w moim przypadku będzie odwrotną stroną i co będzie właścicielem. Przypuszczam, że komentarz w posiadaniu i keywodrach jest odwrotny, ale nie mogę powiedzieć dlaczego. – SET

+0

Słowa kluczowe to strona posiadająca, ponieważ klucz obcy "comment_id" znajduje się w tabeli słów kluczowych. Jednokierunkowy oznacza, że ​​można przejść tylko od komentarza do słów kluczowych, używając komentarza :: getKeywords(). Dwukierunkowe oznacza, że ​​możesz iść w obie strony z dodatkowym słowem kluczowym :: getComment() (brak w moim przykładzie). Rozdział poświęcony stowarzyszeniom jest dość obszerny, ale powinieneś przeczytać rozdziały "Praca z powiązaniami" i "Przypisania skojarzeń", aby uzyskać całą koncepcję. – beberlei