2014-07-24 77 views
1

我有一個表現良好,只有一個問題,我希望我會得到一個答案,如何做我需要做的。Symfony2 FormBuilder與實體類

<?php 

namespace ADS\UserBundle\Form; 

use Symfony\Component\Form\AbstractType; 
use Symfony\Component\Form\FormBuilderInterface; 
use Symfony\Component\OptionsResolver\OptionsResolverInterface; 
use Symfony\Component\Security\Core\SecurityContext; 

class UserType extends AbstractType { 
private $type; 
public function __construct($type) { 
    $this->type = $type; 
} 

public function buildForm(FormBuilderInterface $builder, array $options) { 
    $builder 
     ->add('firstName', 'text', array('required' => true)) 
     ->add('lastName', 'text', array('required' => true)); 
    $builder->add('email', 'email', array('required' => true)); 
    $builder->add('parentCompany', 'entity', array(
     'class' => 'ADSUserBundle:Company', 
     'expanded' => false, 
     'empty_value' => 'CHOOSE ONE', 
     'required' => false, 
     'property' => 'companyName' 
    )) 
    ->add('enabled', 'choice', array('choices' => array('1' => 'Enabled', '0' => 'Disabled'))) 
    ->add('roles', 'entity', array(
      'class' => 'ADSUserBundle:Roles', 
      'required' => true, 
      'property' => 'displayName', 
     )); 
} 

public function setDefaultOptions(OptionsResolverInterface $resolver) { 
    $resolver->setDefaults(array('data_class' => 'ADS\UserBundle\Entity\User')); 
} 

public function getName() { return 'ads_userbundle_user'; } 
} 

我有這種形式,我在看的部分是「角色」部分......現在,它創建了一個多選框(因爲我希望它),雖然值順序即是: 0,1,2,3,4 ...

我真正需要的是弄清楚如何使用這個實體,並且使property成爲displayName(就像現在這樣),並獲得值相應的internalName這樣它會給我一個像這樣的陣列:

array('ROLE_EXAMPLE' => 'EXAMPLE', 'ROLE_EXAMPLE1' => 'EXAMPLE1') 

任何想法如何做到這一點非常感謝。

回答

1

卡米爾Adryjanek是正確的,如果將其從entity更改爲choice字段將會更容易。我已經做了一些測試,包括FOSUserBundle和沒有捆綁 - 在這兩種情況下,我碰到了一些有趣的路障。

首先,我試圖通過QueryBuilderrepository中運行它,但它沒有正常工作。原因是,您想返回array而不是ORM對象的事實會導致錯誤。

接下來,我開始着手創建選擇字段。所有的指南,說使用字段名稱role,而不是roles,所以我試過,但我然後必須從FOSUserBundle複製UserInterface - 我不想這樣做 - 所以在這裏我強調,並試圖找出它出。

這就是我最終做的,這很好。

private $normalRoles = array(); 

然後在__construct我補充一下:$this->normalRoles = $roles;

這裏的建設者:

$builder 
    ->add('roles', 'choice', array(
      'multiple' => true, 
      'choices' => $this->normalRoles 
     )) 
; 

本來,我離開了多出來的部分,搞清楚它會至少讓我看看一個選項框。我最終得到了Array to String轉換錯誤。因此,在'multiple' => true中添加,修復了該錯誤。

然後,在我的倉庫,我創建了一個名爲normalizeRoles

public function normalizeRoles() { 
    $data = array(); 
    $qb = $this->getEntityManager(); 
    $query = $qb->createQuery(
     "SELECT r.internalName, r.displayName FROM AcmeUserBundle:Roles r" 
    )->getArrayResult(); 
    foreach ($query as $k => $v) { 
     $data[$v['internalName']] = $v['displayName']; 
    } 
    return $data; 
} 

從這裏功能,我們只是盡在UserBundleDefaultController一些小的修改在newActioneditAction(兩者是相同的變化)

所以,首先要把你的控制器use Acme/UserBundle/Entity/Roles爲了避免任何錯誤,並能夠得到該存儲庫。

接下來,您創建窗體右側,然後運行normalizeRoles()功能

$roles = $em->getRepository('AcmeUserBundle:Roles')->normalizeRoles()

然後,通過使其通過結構:new UserType($roles)

該是這樣的全系列:

$form = $this->createForm(new UserType($roles), $entity, array(
     'action' => $this->generateUrl('acmd.user.edit', array(
       'id' => $id) 
      ) 
    )); 

或新:

$form = $this->createForm(new UserType($roles), $entity, array(
     'action' => $this->generateUrl('acmd.user.new') 
      ) 
    )); 

此時 - 您將擁有一個工作系統,可讓您動態地將角色添加到數據庫表中,然後將這些角色與新用戶或當前用戶相關聯。

1

您可以嘗試通過query_builder屬性做到這一點:

$builder->add('roles', 'entity', array(
    'class' => 'ADSUserBundle:Roles', 
    'required' => true, 
    'property' => 'displayName', 
    'query_builder' => function (RolesRepository $queryBuilder) { 
     return $queryBuilder->someMethod() // some method in this repository that return correct query to db. 
    }, 
)); 
1

在這種情況下,它會更好地使用choice字段中鍵入(http://symfony.com/doc/current/reference/forms/types/choice.html),而不是實體,並通過一些角色的選擇作爲選項來形成,因爲實體字段類型獲取實體ID作爲選擇鍵:

public function buildForm(FormBuilderInterface $builder, array $options) { 

    ... 

    $builder->add('roles', 'choice', array(
    'choices' => $options['role_choices'] 
)); 

    ... 
} 

public function setDefaultOptions(OptionsResolverInterface $resolver) { 
    $resolver->setDefaults(array(
     'data_class' => 'ADS\UserBundle\Entity\User', 
     'role_choices' => array() 
    )); 
} 

注意:建議通過options參數傳遞變量,而不是構造函數。