2012-11-17 10 views
9

Zastanawiam się, jaki jest najlepszy sposób utworzenia formularza, który obsługuje relację wiele do wielu z dodatkowym polem w symfony2.Renderowanie relacji wiele do wielu z dodatkowymi polami do postaci

Dla przykładu załóżmy, że chciałbym stworzyć funkcję powiadamiania dla użytkowników. Mam obiekty User i Notification. Również, aby móc dodać dodatkowe parametry w relacji wiele do wielu pomiędzy jednostkami, utworzyłem trzeci podmiot: UserNotification. Dodatkowy parametr wskazuje, czy powiadomienie zostało przeczytane, czy nie przez użytkowników.

* @ORM\Entity() */ 
class Notification 
{ 
    /** @Id @Column(type="integer") */ 
    private $id; 

    /** @OneToMany(targetEntity="UserNotification", mappedBy="notification") */ 
    private $usernotifications; 

    /** @Column() */ 
    private $message; 

    ... 
} 

* @ORM\Entity() */ 
class User 
{ 
    /** @Id @Column(type="integer") */ 
    private $id; 

    /** @OneToMany(targetEntity="UserNotification", mappedBy="user") */ 
    private $usernotifications; 

    /** @Column() */ 
    private $name; 

    ... 
} 

* @ORM\Entity() */ 
class UserNotification 
{ 
    /** @ManyToOne(targetEntity="User", inversedBy="usernotifications") 
    private $user; 

    /** @ManyToOne(targetEntity="Message", inversedBy="usernotifications") 
    private $message; 

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

    ... 
} 

ten sposób jestem w stanie uzyskać tego rodzaju danych

 User 
+----+---------+ 
| id | name | 
+----+---------+ 
| 1 | John | 
| 2 | Paul | 
+----+---------+ 

     Notification 
+----+----------------------+ 
| id | message    | 
+----+----------------------+ 
| 1 | Cool stuff   | 
| 2 | Lorem ipsum   | 
+----+----------------------+ 

     UserNotification 
+---------+-----------------+---------+ 
| user_id | notification_id | isRead | 
+---------+-----------------+---------+ 
| 1  |    1 |  1 | 
| 2  |    1 |  0 | 
| 1  |    2 |  0 | 
| 2  |    2 |  1 | 
+---------+-----------------+---------+ 

Ok teraz tutaj jest problem, jak zrobić formularz, który pozwoli na wysłanie powiadomienia do niektórych użytkowników? W klasycznej relacji wielu do wielu nie stanowiło to problemu. Miałem NotificationType z następującym builder:

$builder->add('users', 'entity', array(
       'class' => 'User', 
       'property' => 'name', 
       'multiple' => 'true', 
      )) 
      ->add('message', 'text'); 

Ale ponieważ musiałem utworzyć pośredni UserNotification podmiot, nie mam pojęcia jak to zrobić. Dziękuję za pomoc;)

Odpowiedz

4

Zrobiłem dokładnie to samo. Moja jednostka InternalMessage to Twoja Notification. W formularzu users pole nie jest odwzorowany (property_path jest false) i jest to potwierdzone za pomocą subskrybenta:

public function buildForm(FormBuilder $builder, array $options) 
{ 
    $builder 
     ->add('title', 'text', array(
      'label' => 'Titolo *' 
     )) 
     ->add('content', 'textarea', array(
      'label' => 'Contenuto *' 
     )) 
     ->add('priority', new PriorityType(), array(
      'label' => 'Priorità *' 
     )) 
     ->add('users', 'entity', array(
      'label'   => 'Destinatari *', 
      'class'   => 'Acme\HelloBundle\Entity\User', 
      'property'  => 'select_label', 
      'multiple'  => true, 
      'expanded'  => true, 
      'property_path' => false, 
     )); 
    ; 

    $builder->addEventSubscriber(new AddUsersValidationSubscriber()); 
} 

Chociaż w moim kontrolera, jedyne co mam zrobić (zakładając, że postać jest ważna) jest aby utworzyć jedną InternalMessageFeedback jednostki (takie samo jak UserNotification) dziobowy każdego użytkownika w formie modelu

$message = new InternalMessage(); 
$form = $this->createForm(new InternalMessageType(), $message); 

// ... 

// The sender 
$message->setUser($this->getSecurityContext()->getToken()->getUser()); 

// Persist the inverse side 
$em = $this->getEntityManager(); 
$em->persist($message); 

// One feedback for each user 
/** @var $user \Acme\HelloBundle\Entity\User */ 
foreach($form->get('users')->getData() as $user) { 
    $feedback = new InternalMessageFeedback(); 

    // Se the message and user for current feedback 
    $feedback->setInternalMessage($message); 
    $feedback->setUser($user); 

    // Persist the owning side 
    $em->persist($feedback); 

    // Sync the inverse side 
    $message->addInternalMessageFeedback($feedback); 
} 

$em->flush(); 

Hope this helps :)

+0

Dzięki za y nasza odpowiedź Gremo;) Nie wiedziałem o właściwości 'property_path'. I działa jak urok. –

Powiązane problemy