J'ai des problèmes avec plusieurs à plusieurs relations. J'ai Users
et Assets
. J'aimerais pouvoir affecter des utilisateurs à un actif sur la page de l'actif.
Le code ci-dessous affiche une liste d'utilisateurs lors de la création/modification d'un actif, mais les modifications apportées aux cases à cocher des utilisateurs ne sont pas enregistrées, tant que le reste des données est conservé.
Si j'ajoute une entrée à users_assets via le client mysql, ces modifications sont affichées dans la liste des ressources.
Utilisateur
class User extends BaseUser
{
/**
* @ORM\ManyToMany(targetEntity="Asset", inversedBy="users")
*/
private $assets;
}
Atout
class Asset
{
/**
* @ORM\ManyToMany(targetEntity="User", mappedBy="assets")
*/
private $users;
}
Type d'actif
public function buildForm(FormBuilderInterface $builder, array $options)
{
$form = $builder
->add('users', null, array(
'expanded' => true,
'multiple' => true
))
->getForm();
return $form;
}
Pour une raison quelconque, j'ai dû changer les correspondances de la doctrine pour que cela fonctionne:
Asset:
/**
* @ORM\ManyToMany(targetEntity="Adaptive\UserBundle\Entity\User", inversedBy="assets")
* @ORM\JoinTable(name="user_assets")
*/
private $users;
User:
/**
* @ORM\ManyToMany(targetEntity="Splash\SiteBundle\Entity\Asset", mappedBy="users")
*/
private $assets;
Maintenant, lorsque je sauvegarde l'actif, il enregistre les utilisateurs associés. Je n'avais pas besoin de définir constructeur-> ajouter en tant qu'entité ou collection. Je passe simplement la valeur null et utilise les informations de mappage pour renseigner les informations d'entité:
AssetType:
->add('users', null, array('expanded' => "true", "multiple" => "true"))
Je ne sais pas trop pourquoi j'avais besoin des informations inversedBy et JoinTable sur Asset vs The User, mais cela semble fonctionner maintenant!
Merci pour les suggestions !!!
Pas tout à fait sûr pourquoi je devais avoir les informations inversedBy et JoinTable sur l'actif par rapport à l'utilisateur mais cela Semble fonctionner maintenant!
La raison pour laquelle vos modifications ont été ignorées est que la doctrine ne persiste que si elles sont modifiées par le côté propriétaire d'une relation (comme l'a dit @ Florian).
C'est le lien vers la documentation de Doctrine où ce comportement est expliqué: http://docs.doctrine-project.org/en/latest/reference/unitofwork-associations.html
Assez bizarre, j'ai rencontré le même problème en 2016 et j'avais toujours du mal à trouver la solution. Je vais le partager pour les futurs googleurs:
Le problème est que ce que symfony fait essentiellement lorsque vous enregistrez le formulaire est le suivant:
$asset->getUsers()->add($user)
Et comme vous êtes à l’inverse de la relation, vos modifications ne seront pas conservées.
Ce dont vous avez vraiment besoin est de faire en sorte que cela appelle ceci:
$asset->addUser($user)
Où addUser () est défini de la manière suivante sur l'entité Asset:
public function addUser(User $user)
{
//add to the inverse side
$this->users->add($user);
//add on the owning side (only this is persisted)
$user->addAsset($this); //$user->assets->add($asset);
}
Donc, pour que symfony utilise cette méthode $asset->addUser()
, vous devez définir
'by_reference' => false
sur votre champ users
pour le formulaire AssetType
.
Plus d'informations sur ce paramètre ici http://symfony.com/doc/current/reference/forms/types/form.html#by-reference
N'oubliez pas que vous devez également définir la méthode removeUser()
de la même manière (afin qu'elle supprime l'entité de la relation propriétaire).
Au début, vous devriez supprimer le préfixe barre oblique inverse dans les annotations (voir notice ici ).
Et vous devez utiliser le type de champ d'entité:
$builder->add('users', 'entity', array(
'class' => 'AdaptiveUserBundle:User',
'expanded' => true,
'multiple' => true,
'query_builder' => function(EntityRepository $er) {
return $er->createQueryBuilder('u')
->orderBy('u.username', 'ASC');
},
));
Vous devez utiliser le type de champ 'collection' dans votre formulaire.
$builder->add('users', 'collection', array(
'type' => new UserType(),
'prototype' => true,
'allow_add' => true,
'allow_delete' => true
));
Vous devez évidemment créer le formulaire UserType()
en premier.
Voici toutes les informations dont vous aurez besoin, y compris des exemples de code:
http://symfony.com/doc/current/cookbook/form/form_collections.html
http://symfony.com/doc/current/reference/forms/types/collection.html