Note that there are some explanatory texts on larger screens.

plurals
  1. PO
    text
    copied!<h1>1. The workaround solution</h1> <p>The workaround solution suggested by Jeppe Marianger-Lam is at the moment the only one working I know of.</p> <h3>1.1 Why did it stop working in my case?</h3> <p>I changed my RoleNameType (for other reasons) to:</p> <ul> <li>ID (hidden)</li> <li>name (custom type - label)</li> <li>module &amp; description (hidden, read-only)</li> </ul> <p>The problem was my custom type label rendered NAME property as</p> <pre> &lt;span&gt; role name &lt;/span&gt; </pre> <p>And since it was not "read only" the FORM component expected to get NAME in POST.</p> <p>Instead only ID was POSTed, and thus FORM component assumed NAME is NULL.</p> <p>This lead to CASE 2 (3.2) -> creating association, but overwriting ROLE NAME with an empty string.</p> <h1>2. So, what exacly is this workaround about?</h1> <h3>2.1 Controller</h3> <p>This workaround is very simple.</p> <p>In your controller, before you VALIDATE the form, you have to fetch the posted entity identyficators and get matching entities, then set them to your object.</p> <pre><code>// example action public function createAction(Request $request) { $em = $this-&gt;getDoctrine()-&gt;getEntityManager(); // the workaround code is in updateUser function $user = $this-&gt;updateUser($request, new User()); $form = $this-&gt;createForm(new UserType(), $user); if($request-&gt;getMethod() == 'POST') { $form-&gt;bindRequest($request); if($form-&gt;isValid()) { /* Persist, flush and redirect */ $em-&gt;persist($user); $em-&gt;flush(); $this-&gt;setFlash('avocode_user_success', 'user.flash.user_created'); $url = $this-&gt;container-&gt;get('router')-&gt;generate('avocode_user_show', array('id' =&gt; $user-&gt;getId())); return new RedirectResponse($url); } } return $this-&gt;render('AvocodeUserBundle:UserManagement:create.html.twig', array( 'form' =&gt; $form-&gt;createView(), 'user' =&gt; $user, )); } </code></pre> <p>And below the workaround code in updateUser function:</p> <pre><code>protected function updateUser($request, $user) { if($request-&gt;getMethod() == 'POST') { // getting POSTed values $avo_user = $request-&gt;request-&gt;get('avo_user'); // if no roles are posted, then $owned_roles should be an empty array (to avoid errors) $owned_roles = (array_key_exists('avoRoles', $avo_user)) ? $avo_user['avoRoles'] : array(); // foreach posted ROLE, get it's ID foreach($owned_roles as $key =&gt; $role) { $owned_roles[$key] = $role['id']; } // FIND all roles with matching ID's if(count($owned_roles) &gt; 0) { $em = $this-&gt;getDoctrine()-&gt;getEntityManager(); $roles = $em-&gt;getRepository('AvocodeUserBundle:Role')-&gt;findById($owned_roles); // and create association $user-&gt;setAvoRoles($roles); } return $user; } </code></pre> <p>For this to work your SETTER (in this case in User.php entity) must be:</p> <pre><code>public function setAvoRoles($avoRoles) { // first - clearing all associations // this way if entity was not found in POST // then association will be removed $this-&gt;getAvoRoles()-&gt;clear(); // adding association only for POSTed entities foreach($avoRoles as $role) { $this-&gt;addAvoRole($role); } return $this; } </code></pre> <h1>3. Final thoughts</h1> <p>Still, I think this workaround is doing the job that</p> <pre><code>$form-&gt;bindRequest($request); </code></pre> <p>should do! It's either me doing something wrong, or symfony's Collection form type is not complete.</p> <p><a href="http://symfony.com/blog/towards-symfony-2-1" rel="nofollow noreferrer" title="Towards Symfony 2.1 by Fabien Potencier – May 29, 2012">There are some major changes in Form component</a> comeing in symfony 2.1, hopefully this will be fixed.</p> <h3>PS. If it's me doing something wrong...</h3> <p>... please post the way it should be done! I'd be glad to see a quick, easy and "clean" solution. </p> <h3>PS2. Special thanks to:</h3> <p>Jeppe Marianger-Lam and userfriendly (from #symfony2 on IRC). You've been very helpful. Cheers!</p>
 

Querying!

 
Guidance

SQuiL has stopped working due to an internal error.

If you are curious you may find further information in the browser console, which is accessible through the devtools (F12).

Reload