2012-02-01 15 views
18

Sto avendo qualche problema con una relazione molti a molti. Ho Users e Assets. Vorrei poter assegnare utenti a un asset nella pagina dell'asset.Symfony2 Doctrine2 Molti a molti moduli non salvano le entità

Il codice seguente mostra un elenco di utenti durante la creazione/modifica di un asset, tuttavia le modifiche apportate alle caselle di controllo dell'utente non vengono salvate, mentre il resto dei dati viene mantenuto.

Se aggiungo una voce a users_assets tramite il client mysql, queste modifiche vengono visualizzate nell'elenco delle risorse.

utente

class User extends BaseUser 
{ 
    /** 
    * @ORM\ManyToMany(targetEntity="Asset", inversedBy="users") 
    */ 
    private $assets; 
} 

Asset

class Asset 
{ 
    /** 
    * @ORM\ManyToMany(targetEntity="User", mappedBy="assets") 
    */ 
    private $users; 
} 

AssetType

public function buildForm(FormBuilderInterface $builder, array $options) 
{ 
    $form = $builder 
     ->add('users', null, array(
      'expanded' => true, 
      'multiple' => true 
     )) 
     ->getForm(); 

    return $form; 
} 
+0

non dovresti chanage 'null' a' EntityType'? Cosa intendi con null ?! – Trix

risposta

29

Per qualche motivo ho dovuto cambiare le mappature dottrina per arrivare a questo lavoro:

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; 

Ora quando salvo il bene salva gli utenti associati. Non avevo bisogno di definire builder-> aggiungi come entità o collezione. Ho semplicemente passare nullo e utilizza le informazioni di mappatura di compilare le informazioni entità:

AssetType: 
->add('users', null, array('expanded' => "true", "multiple" => "true")) 

Non esattamente sicuro perché avevo bisogno di avere l'inversedBy e informazioni JoinTable sul Asset vs L'utente, ma sembra funzionare adesso!

Grazie per i suggerimenti !!!

+0

Avevo problemi simili. Suggerimenti agli altri: assicurati che tutti i tuoi singolari/plurali siano ciò che dovrebbero essere, e se una delle tue entità ha un nome a più termini (ad esempio 'CoolDude'), potresti trarre beneficio dal fatto che l'impostazione predefinita di Doctrine è supponiamo che il nome della tua tabella sia solo la versione con una versione inferiore di quella, ad es 'Cooldude'. Se in realtà è 'cool_dude', penso che dovrai impostarlo esplicitamente. Puoi vedere come nei documenti di Doctrine. http://docs.doctrine-project.org/projects/doctrine-orm/en/2.0.x/reference/association-mapping.html#many-to-many-bidirectional –

+0

Il problema è quando si desidera un modulo simile sul lato inverso: non funzionerebbe. –

+0

Soluzione che non funziona per me, la mia tabella di join è sempre vuota! – Fabien

0

È necessario utilizzare 'collezione' fie Digita il tuo modulo.

$builder->add('users', 'collection', array(
    'type' => new UserType(), 
    'prototype' => true, 
    'allow_add' => true, 
    'allow_delete' => true 
)); 

È necessario creare prima il modulo UserType().

Ecco tutte le informazioni che avrete bisogno, tra cui esempi di codice:

http://symfony.com/doc/current/cookbook/form/form_collections.html

http://symfony.com/doc/current/reference/forms/types/collection.html

+0

Ho pensato che passando nullo avrebbe assunto questo tipo, attraverso i miei mapping di dottrina. Ho una configurazione simile utilizzando le categorie sulle risorse e funziona benissimo. Questo è il codice che devo popolare nelle raccolte delle categorie: -> add ('categories', null, array ('expanded' => "true", "multiple" => "true")) ... anche io non è necessario aggiungere funzionalità crude per gli utenti nell'asset, ma ho semplicemente bisogno di essere in grado di assegnare gli utenti correnti a quell'asset –

+1

Infatti, doctrine dall'estensione aggiunge un indovino basato sui metadati. Se hai definito correttamente l'associazione ManyToMany, il tipo guesser configurerà il tuo campo come 'collection'. Con * correttamente *, intendo che il ** proprietario ** dell'associazione deve essere il "Bene" nel tuo caso, ecco perché è stato necessario invertire la mappatura. – Florian

+0

Qual'è il problema con 'EntityType' +' Expanded' + 'Multiple'? – Trix

4

In un primo momento si dovrebbe cadere prefisso backslash nelle annotazioni (vedi nota here).

E avete bisogno di utilizzare il tipo di campo 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'); 
    }, 
)); 
17

Non esattamente sicuro perché avevo bisogno di avere l'inversedBy e JoinTable informazioni sull'attività vs L'utente ma sembra funzionare ora!

Il motivo per cui le modifiche sono state ignorate è che la dottrina persiste solo cambiamenti dal lato proprietario di una relazione (come ha detto @Florian).

questo è il link alla documentazione di Doctrine in cui è illustrato questo comportamento: http://docs.doctrine-project.org/en/latest/reference/unitofwork-associations.html

9

Strano abbastanza Ho affrontato lo stesso problema nel 2016 e aveva ancora difficoltà a trovare la soluzione. Io condivido per Googler futuri:

Il problema è che ciò che symfony essenzialmente fa quando si salva la forma è questo:

$asset->getUsers()->add($user)

E perché sei sul lato inverso della relazione è non persisterà le tue modifiche.

Quello che si ha realmente bisogno è quello di fare in modo che chiama questo:

$asset->addUser($user)

Dove addUser() è definito come segue sull'entità patrimoniale:

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

Quindi, per far sì che symfony usi il metodo $asset->addUser(), devi impostare

'by_reference' => false

sul users campo per AssetType modulo.

più su questa impostazione qui http://symfony.com/doc/current/reference/forms/types/form.html#by-reference

Ricordatevi che anche necessario definire removeUser() metodo nello stesso modo (in modo che rimuove entità dalla relazione possedere)

+0

Questa dovrebbe essere la risposta accettata.Mi stavo chiedendo, facendo qualche post retro, perché nessuno ha scritto questo e alla fine è arrivato con il tuo. Ben fatto. – DonCallisto

+0

** L'asset ** è di proprietà qui, quindi questo è in conflitto con [Doctrine Documentation] (http://docs.doctrine-project.org/projects/doctrine-orm/en/latest/reference/association-mapping.html# Owning-and-inverse-side-on-a-manytomany-association) – Trix

+0

@Trix Grazie, ho appena controllato di nuovo e c'era davvero una confusione di utenti/risorse. Ho apportato una modifica - la soluzione è sempre la stessa, ho solo modificato i nomi delle variabili per essere coerenti. –

Problemi correlati