Création à la main d'une table intermédiaire

Le problème exposé dans ce sujet a été résolu.

Bonjour,

Je suis confronté à un problème, que je n'arrive pas à résoudre. Je suis en train de développer une application de gestion de bibliothèque personnelle.

J'ai une entité User et une entité Book. Un Book est unique par son ISBN. Un utilisateur peut avoir dans sa bibliothèque plusieurs livres. Un livre peut être dans plusieurs bibliothèque. Dans un monde simple, je ne m'occuperai pas de la table intermédiaire ; sauf que là, j'ai besoin d'infos supplémentaires dans cette table. Le livre peut avoir différents états : own, read, want. Je suis donc obligé de faire à la main cette table intermédiaire (Library). Au final, voici ce que je voudrais :

1
2
3
4
5
6
7
8
9
+------+          +---------+          +------+ 
| User |          | Library |          | Book |
|======| -------> |=========| <------- |======|
|id    |          |user_id  |          |id    |
+------+          |book_id  |          +------+
                  |own      |
                  |read     |
                  |want     |
                  +---------+

Je souhaiterais, depuis l'entity User, ajouter un Book dans Library :

1
2
<?php
$this->getUser()->addBook($book);

Mais je bloque. Je n'arrive pas à voir comment écrire mes annotations pour obtenir ce que je veux. D'ailleurs, je ne suis même pas sûr qu'en terme de conception mon approche soit la bonne. C'est pourquoi je me tourne vers vous. :-)

+0 -0

Salut !

C'est relativement simple : tu as une One(User)ToMany(Library) et une Many(Library)ToOne(Book), et les deux relations sont probablement dans les deux sens. Tout le truc vient de ce que cette entité Library doit être créé "manuellement" quand un utilisateur choisit un livre si le statut coule de source. Sinon, je verrais bien une collection de Library dans User. Le formulaire de Library permet de choisir un livre et le statut.

Pour le statut, d'ailleurs, est-ce qu'un livre peut être à la fois voulu, lu et possédé ?

+0 -0

Salut Ymox et merci pour ta réponse. :-)

C'est ce que j'avais fait au début, sauf que quand je génère les méthodes via la console, j'obtiens un "addLibrary" dans User (qui attend donc une entité Library), sauf que je voudrais un "addBook" qui attend une entité Book (j'ai également un "addLibrary" dans Book, même si a priori je n'ai pas à ajouter une entrée depuis l'entité Book). A moins que je m'y prenne mal, ce qui est fort possible.

Pour le statut, on peut avoir :

  • own
  • own | read
  • read
  • read | want
  • want

Il est impossible d'avoir les 3 en même temps (il est surtout impossible que own et want existent ensemble).

User
 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
12
13
14
15
16
17
18
19
<?php
class User extends BaseUser
{
    /**
     * @ORM\Column(name="id", type="integer")
     * @ORM\Id
     * @ORM\GeneratedValue(strategy="AUTO")
     */
    protected $id;

    /**
     * @ORM\OneToMany(targetEntity="Library", mappedBy="user", cascade={"all"})
     */
    private $library;

    public function __construct() {
        $this->library = new ArrayCollection();
    }
}
Book
 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
12
13
14
15
16
17
18
19
<?php
class Book
{
    /**
     * @ORM\Column(name="id", type="integer")
     * @ORM\Id
     * @ORM\GeneratedValue(strategy="AUTO")
     */
    private $id;

    /**
     * @ORM\OneToMany(targetEntity="Library", mappedBy="book")
     */
    private $libraries;

    public function __construct() {
      $this->libraries  = new ArrayCollection();
  }
}
Library

  1
  2
  3
  4
  5
  6
  7
  8
  9
 10
 11
 12
 13
 14
 15
 16
 17
 18
 19
 20
 21
 22
 23
 24
 25
 26
 27
 28
 29
 30
 31
 32
 33
 34
 35
 36
 37
 38
 39
 40
 41
 42
 43
 44
 45
 46
 47
 48
 49
 50
 51
 52
 53
 54
 55
 56
 57
 58
 59
 60
 61
 62
 63
 64
 65
 66
 67
 68
 69
 70
 71
 72
 73
 74
 75
 76
 77
 78
 79
 80
 81
 82
 83
 84
 85
 86
 87
 88
 89
 90
 91
 92
 93
 94
 95
 96
 97
 98
 99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
<?php
/**
 * Library
 *
 * @ORM\Entity(repositoryClass="Bundle\Repository\LibraryRepository")
 * @ORM\Table(name="library")
 * @UniqueEntity({"book", "user"})
 */
class Library
{
    /**
     * @ORM\Column(name="id", type="integer")
     * @ORM\Id
     * @ORM\GeneratedValue(strategy="AUTO")
     */
    protected $id;

    /**
     * @ORM\Column(name="own", type="boolean", nullable=true, options={"default":0})
     */
    private $own;

    /**
     * @ORM\Column(name="read", type="boolean", nullable=true, options={"default":0})
     */
    private $read;

    /**
     * @ORM\Column(name="want", type="boolean", nullable=true, options={"default":0})
     */
    private $want;

    /**
     * @var Book $book
     *
     * @ORM\ManyToOne(targetEntity="Book", inversedBy="libraries")
     * @ORM\JoinColumn(name="book_id", referencedColumnName="id", nullable=false)
     */
    private $book;

    /**
     * @var User $user
     *
     * @ORM\ManyToOne(targetEntity="User", inversedBy="library")
     * @ORM\JoinColumn(name="user_id", referencedColumnName="id", nullable=false)
     */
    private $user;

    /**
     * Get id
     *
     * @return integer 
     */
    public function getId()
    {
        return $this->id;
    }

    /**
     * Set own
     *
     * @param boolean $own
     * @return Library
     */
    public function setOwn($own)
    {
        $this->own = $own;

        return $this;
    }

    /**
     * Get own
     *
     * @return boolean 
     */
    public function getOwn()
    {
        return $this->own;
    }

    /**
     * Set read
     *
     * @param boolean $read
     * @return Library
     */
    public function setRead($read)
    {
        $this->read = $read;

        return $this;
    }

    /**
     * Get read
     *
     * @return boolean 
     */
    public function getRead()
    {
        return $this->read;
    }

    /**
     * Set want
     *
     * @param boolean $want
     * @return Library
     */
    public function setWant($want)
    {
        $this->want = $want;

        return $this;
    }

    /**
     * Get want
     *
     * @return boolean
     */
    public function getWant()
    {
        return $this->want;
    }

    /**
     * Set book
     *
     * @param Book $book
     * @return Library
     */
    public function setBook(Book $book)
    {
        $this->book = $book;

        return $this;
    }

    /**
     * Get book
     *
     * @return Book
     */
    public function getBook()
    {
        return $this->book;
    }

    /**
     * Set user
     *
     * @param User $user
     * @return Library
     */
    public function setUser(User $user)
    {
        $this->user = $user;

        return $this;
    }

    /**
     * Get user
     *
     * @return User
     */
    public function getUser()
    {
        return $this->user;
    }
}

+0 -0

Le fait d'avoir des addLibrary est totalement normal : la liaison est bien entre User/Book et Library, on ne va donc pas ajouter directement un livre à un utilisateur ou vice-versa.

Au final, si tu souhaites vraiment n'avoir à choisir que les livres pour un utilisateur, ce que je ferais c'est d'ajouter un champ non-mappé au formulaire qui affiche tous les livres, et il va te falloir faire un traitement manuel dans ton contrôleur pour créer les objets Library (sans parler du traitement qu'il faudra refaire pour réafficher les livres ainsi liés aux utilisateurs) à partir des livres choisis.

+0 -0

C'est justement ce que je voulais éviter ; je pensais pouvoir le déléguer entièrement à Doctrine. D'où mon problème de mapping.

Tant pis, je vais le faire à la main alors, en créant un manager et un repo.

Merci beaucoup pour ton aide Ymox ! :-D

+1 -0
Connectez-vous pour pouvoir poster un message.
Connexion

Pas encore membre ?

Créez un compte en une minute pour profiter pleinement de toutes les fonctionnalités de Zeste de Savoir. Ici, tout est gratuit et sans publicité.
Créer un compte