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 :)
希望这可以帮助 :)