使用额外字段将多对多关系呈现为表单

时间:2022-11-28 09:53:24

I'm wondering what is the best way to create a form that handle a many-to-many relation with extra field in symfony2.

我想知道在symfony2中创建一个处理与多余字段的多对多关系的表单的最佳方法是什么。

For the example let's say I would like to create a notifying feature for users. I have the User and the Notification entities. Also in order to be able to add extra parameters in the many-to-many relation between entities, I created a third entity UserNotification. The extra parameter indicates if the notification has been read or not by the users.

举个例子,假设我想为用户创建一个通知功能。我有用户和通知实体。另外,为了能够在实体之间的多对多关系中添加额外参数,我创建了第三个实体UserNotification。额外参数指示用户是否已读取通知。

* @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;

    ...
}

This way I am able to get this kind of data

这样我就能得到这种数据

      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 now here is the problem, how to make a form which allow to send a notification to some users? With a classic many-to-many relation it was not a problem. I had a NotificationType with the following builder:

好了,现在问题是,如何制作一个允许向某些用户发送通知的表单?凭借经典的多对多关系,这不是问题。我有一个带有以下构建器的NotificationType:

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

But since I had to create the intermediate UserNotification entity, I have no idea how to do it. Thanks for your help ;)

但由于我必须创建中间UserNotification实体,我不知道如何做到这一点。谢谢你的帮助 ;)

1 个解决方案

#1


4  

I did exactly the same. My InternalMessage entity is your Notification. In the form, users field is not mapped (property_path is false) and it's validated using a subscriber:

我做的完全一样。我的InternalMessage实体是您的通知。在表单中,不映射users字段(property_path为false),并使用订阅者验证它:

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());
}

While in my controller, the only thing i have to do (assuming that form is valid) is to create one InternalMessageFeedback entity (the same as your UserNotification) fore each user in form model:

在我的控制器中,我唯一要做的事情(假设表单有效)是在表单模型中为每个用户创建一个InternalMessageFeedback实体(与UserNotification相同):

$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 :)

希望这可以帮助 :)

#1


4  

I did exactly the same. My InternalMessage entity is your Notification. In the form, users field is not mapped (property_path is false) and it's validated using a subscriber:

我做的完全一样。我的InternalMessage实体是您的通知。在表单中,不映射users字段(property_path为false),并使用订阅者验证它:

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());
}

While in my controller, the only thing i have to do (assuming that form is valid) is to create one InternalMessageFeedback entity (the same as your UserNotification) fore each user in form model:

在我的控制器中,我唯一要做的事情(假设表单有效)是在表单模型中为每个用户创建一个InternalMessageFeedback实体(与UserNotification相同):

$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 :)

希望这可以帮助 :)