2013-05-13 54 views
3

我已經擴展了SonataAdmin類FOSUser和加入2-自定義字段(來自外部數據源的選擇型):CompanySector奏用戶管理 - 自定義字段依賴性

我想使Sector依賴Company,所以如果用戶選擇公司,它會過濾可用的扇區。

我雖然有關使用FormEvents在頁面加載過濾,但我甚至不知道如何獲得當前窗體的Company值。

這裏是我的自定義SectorType

public function buildForm(FormBuilderInterface $builder, array $options) 
{ 
    $builder->addEventListener(FormEvents::PRE_SET_DATA 
    , function(FormEvent $event) { 
     $data = $event->getData(); 
     $form = $event->getForm(); 
     // Need to get the company value here if set 
    }); 
} 

public function setDefaultOptions(OptionsResolverInterface $resolver) 
{ 
    $resolver->setDefaults(array(
     'choices' => $this->getSectors(), 
    )); 
} 

public function getSectors() 
{ 
    $sects = array(); 
    // Need to pass the selected company value to my getList 
    // (which gets the list of sector as you can imagine) 
    if (($tmp_sects = $this->ssrs->getList('Sector'))) { 
     foreach ($tmp_sects as $sect) { 
      $label = $sect['id'] ? $sect['label'] : ''; 
      $sects[$sect['id']] = $label; 
     } 
    } 
    return $sects; 
} 

的一部分,所以現在的問題是:

如何從我的自定義SectorType選擇Company


之後,我需要能夠刷新該部門使用Ajax,但是這將是另外一個問題

+0

看看這個問題找到答案:http://stackoverflow.com/questions/10118868/how-to-use-ajax-within-sonata-admin-forms! – miragedesign 2013-07-25 09:41:44

回答

1

我也有類似的問題。我需要創建一個銷售實體,它需要與企業實體建立多對一的關係,並與服務實體建立多對多的關係。這裏是銷售實體:

事情是那裏的服務取決於所選擇的公司。例如服務a和b只能提供給公司x。而服務b和c只能提供給y公司。所以在我的管理員中,取決於所選公司,我必須顯示可用的服務。對於這些我需要做兩件事:

首先創建一個動態的形式與我的銷售管理員,這樣在服務器端我可以得到正確的服務可用於我的銷售記錄中指定的公司。其次,我要創建爲我公司表單元素自定義表單類型,這樣,當它是由客戶端上的用戶改變,它會發送一個Ajax請求得到正確的服務選擇的公司。

對於我的第一個問題,我做了類似於你想實現的東西,但不是創造我的服務元素的特定的自定義類型,我在管理直接加入DE事件偵聽器。

這裏是銷售實體:

/** 
* 
* @ORM\Table(name="sales") 
* @ORM\Entity 
* @ORM\HasLifecycleCallbacks() 
*/ 
class Sale 
{ 
    /** 
    * @var integer $id 
    * 
    * @ORM\Column(name="id", type="integer", nullable=false) 
    * @ORM\Id 
    * @ORM\GeneratedValue(strategy="IDENTITY") 
    */ 
    public $id; 
    /** 
    * @ORM\ManyToOne(targetEntity="Branch") 
    * @ORM\JoinColumn(name="branch_id", referencedColumnName="id", nullable = false) 
    * @Assert\NotBlank(message = "Debe especificar una empresa a la cual asignar el precio de este exámen!") 
    */ 
    private $branch; 

    /** Unidirectional many to many 
    * @ORM\ManyToMany(targetEntity="Service") 
    * @ORM\JoinTable(name="sales_services", 
    *  joinColumns={@ORM\JoinColumn(name="sale_id", referencedColumnName="id")}, 
    *  inverseJoinColumns={@ORM\JoinColumn(name="service_id", referencedColumnName="id")} 
    *  ) 
    * @Assert\Count(min = "1", minMessage = "Debe especificar al menos un servicio a realizar!") 
    */ 
    private $services; 


    public function __construct() { 
     $this->services = new \Doctrine\Common\Collections\ArrayCollection(); 
    } 

    /** 
    * Get id 
    * 
    * @return integer 
    */ 
    public function getId() 
    { 
     return $this->id; 
    } 

    /** 
    * Set branch 
    * 
    * @param Astricom\NeurocienciasBundle\Entity\Branch $branch 
    */ 
    //default value always have to be null, because when validation constraint is set to notblank, 
    //if default is not null, before calling the validation constraint an error will pop up explaining 
    //that no instance of Branch was passed to the $branch argument. 
    public function setBranch(\Astricom\NeurocienciasBundle\Entity\Branch $branch = null) 
    { 
     $this->branch = $branch; 
    } 

    /** 
    * Get branch 
    * 
    * @return Astricom\NeurocienciasBundle\Entity\Branch 
    */ 
    public function getBranch() 
    { 
     return $this->branch; 
    } 

    /** 
    * Add service 
    * 
    * @param \Astricom\NeurocienciasBundle\Entity\Service|null $service 
    */ 
    public function addServices(\Astricom\NeurocienciasBundle\Entity\Service $service = null) 
    { 
     $this->services[] = $service; 
    } 

    /** 
    * Get services 
    * 
    * @return Doctrine\Common\Collections\Collection 
    */ 
    public function getServices() 
    { 
     return $this->services; 
    } 


    /** 
    * Sets the creation date 
    * 
    * @param \DateTime|null $createdAt 
    */ 
    public function setCreatedAt(\DateTime $createdAt = null) 
    { 
     $this->createdAt = $createdAt; 
    } 

    /** 
    * Returns the creation date 
    * 
    * @return \DateTime|null 
    */ 
    public function getCreatedAt() 
    { 
     return $this->createdAt; 
    } 

    /** 
    * Sets the last update date 
    * 
    * @param \DateTime|null $updatedAt 
    */ 
    public function setUpdatedAt(\DateTime $updatedAt = null) 
    {  
     $this->updatedAt = $updatedAt; 
    } 

所以後來在管理表單生成器:

protected function configureFormFields(FormMapper $formMapper) { 
    $em = $this->container->get('doctrine')->getEntityManager(); 
    $branchQuery = $em->createQueryBuilder(); 

    $branchQuery->add('select', 'b') 
     ->add('from', 'Astricom\NeurocienciasBundle\Entity\Branch b') 
     ->add('orderBy', 'b.name ASC'); 

    $formMapper 
     ->with('Empresa/Sucursal') 
     ->add('branch','shtumi_ajax_entity_type',array('required' => true, 'label'=>'Empresa/Sucursal','error_bubbling' => true, 'empty_value' => 'Seleccione una empresa/sucursal', 'empty_data' => null, 'entity_alias'=>'sale_branch', 'attr'=>array('add_new'=>false), 'model_manager' => $this->getModelManager(), 'class'=>'Astricom\NeurocienciasBundle\Entity\Branch', 'query' => $branchQuery)) 
     ->end() 
    ; 

    $builder = $formMapper->getFormBuilder(); 
    $factory = $builder->getFormFactory(); 
    $sale = $this->getSubject(); 
    $builder->addEventListener(FormEvents::PRE_SET_DATA, 
     function(DataEvent $event) use ($sale,$factory, $em) { 

      $form = $event->getForm(); 
      $servicesQuery = $em->createQueryBuilder(); 
      $servicesQuery->add('select','s') 
       ->add('from','Astricom\NeurocienciasBundle\Entity\Service s'); 

      if (!$sale || !$sale->getId()) { 
       $servicesQuery 
        ->where($servicesQuery->expr()->eq('s.id', ':id')) 
        ->setParameter('id', 0); 
      } 
      else { 
       $servicesQuery 
        ->join('s.branch', 'b') 
        ->where($servicesQuery->expr()->eq('b.id', ':id')) 
        ->setParameter('id', $sale->getBranch()->getId()); 
      } 

      $form->add($factory->createNamed('services','entity',null,array('required' => true, 'label'=>'Servicios','error_bubbling' => true, 'attr'=>array('show_value_label'=>true),'class'=>'Astricom\NeurocienciasBundle\Entity\Service','multiple'=>true,'expanded'=>true,'query_builder'=>$servicesQuery))); 
     } 
    ); 
} 

訣竅的事情是通過表格數據。在事件監聽器的函數中使用evet-> getData()不起作用。相反,我通過admin-> getSubject()方法傳遞它。然後,而不是添加sonataadmin表單類型,事件偵聽器的功能裏面,我不得不用一個簡單的symfony的表單類型。

您提到的Ajax部分是另一個問題。表單構建器中分支上的所有奇怪事物都添加了方法,這與此問題的自定義字段類型有關。不要擔心。