父表单类型类无法访问子项的私有属性

时间:2017-09-19 15:13:08

标签: php forms symfony null symfony-forms

我确信这是一个非常愚蠢的问题,但我不知道如何解决它。

我有一个表单类型:

  class DocumentDeactivationType extends DocumentFilterType {

      private $tokenStorage;

      public function __construct(TokenStorageInterface $tokenStorage)
      {
          $this->tokenStorage = $tokenStorage;
      }
      public function buildForm(FormBuilderInterface $builder, array $options)
      {
          parent::buildForm($builder, $options);
          $builder  ->add('documentlist', EntityType::class, array(
              'class' => 'DocumentBundle:Document',
              'property' => 'name',
              'expanded' => false, 'multiple' => true,
              'label' => 'label.document_list',
              'empty_value' => "Select document",
              'required' => false,
              'mapped' => false,
              'translation_domain' => 'Documents',
          ));
      }

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

扩展了过滤器表单类型:

  class DocumentFilterType extends AbstractType {

      private $tokenStorage;

      public function __construct(TokenStorageInterface $tokenStorage)
      {
          $this->tokenStorage = $tokenStorage;
      }
      public function buildForm(FormBuilderInterface $builder, array $options)
      {
          $builder
              ->setAction($options['data']['url'])
              ->setMethod('GET')
              ->add('type', 'choice', array('choices' => array(
                  'document_types.contract' => 1,
                  'document_types.general'=>2,
                  'document_types.goodwill_policy'=>3,
                  'document_types.pricesheet'=>4,
                  'document_types.yq_update'=>5,
                  'document_types.contract_addendum'=>6),
                  'choices_as_values' => true, 'label' => 
                  'label.types',
                  'expanded' => false, 'multiple' => true,
                  'label' => 'label.type', 'required' => false,
                  'translation_domain' => 'Documents'));

              $user = $this->tokenStorage->getToken()->getUser();

              $builder->addEventListener(FormEvents::PRE_SET_DATA, function (FormEvent $event) use ($user){
                  $form = $event->getForm();     
                  // only show specific filters based on user's context

                  $form->add('airlines', 'entity', array(
                      'class' => 'AppBundle:Airline', 'property' => 'id',
                      'query_builder' => function (EntityRepository $er) use ($user) {
                          $airlines = $user->getAirlines();
                          return $er->createQueryBuilder('a')
                              ->addOrderBy('a.id', 'ASC')
                              ->andWhere('a.id IN (?1)')
                              ->setParameter(1,$airlines);
                      },
                     'choice_value' => 'id',
                     'choice_label' => 'id', 'label' => 
                     'label.airlines',
                     'expanded' => false, 'multiple' => true, 'required' => false,
                     'translation_domain' => 'Documents'));

                  $form->add('markets', 'entity', array(
                      'class' => 'AppBundle:Market', 'property' => 'id',
                      'query_builder' => function (EntityRepository $er) use ($user) {
                          $markets = $user->getMarkets();
                          return $er->createQueryBuilder('m')
                             ->addOrderBy('m.id', 'ASC');
                             // ->andWhere('m.id IN (?1)')
                             // ->setParameter(1,$markets);
                      },
                      'choice_value' => 'id',
                      'choice_label' => 'id', 'label' => 'label.markets',
                      'expanded' => false, 'multiple' => true, 'required' => false,
                      'translation_domain' => 'Documents'));

                  });
      }

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

现在这种过滤器类型有多次使用,并且始终有效。我现在为DeactivationType添加了一个动作,当转到该路径时,我得到以下异常,这个异常显然发生在我的DocumentFilterType中:

Call to a member function getToken() on null

我不明白为什么错误只发生在那条路线上,因为它适用于其他所有场合。 这是引用DocumentDeactivationType的动作:

    /**
* @Route("/create2", name="documentBundle_create2_document", requirements={"id" = "\d+"}, defaults={"id" = 0, "filter" = null})
* @Template()
*/
public function nextAction(Request $request, $id){

  // filters: type, markets, airlines
  $type = $request->query->get('type');
  $markets = $request->query->get('markets');
  $airlines = $request->query->get('airlines');

  //create filter form
  $url = $this->get('router')->generate('documentBundle_create2_document', array(
        'page' => 1
  ));
  $filterForm = $this->createForm(DocumentDeactivationType::class, array(
    'type' => $type,
    'markets' => $markets,
    'airlines'=>$airlines,
    'url' => $url
  ));
  $filterForm->handleRequest($request);
  if ($filterForm->isSubmitted() && $filterForm->isValid())
  {
    $type = $filterForm->get('type')->getData();
    $markets = $filterForm->get('markets')->getData();
    $airlines=$filterForm->get('airlines')->getData();

    $this->addFlash(
    'success',
    'The document has been deactivated!'
    );
    return $this->redirectToRoute('documentBundle_document_list');
  } else {
    /*
    * DISPLAY ERROR MESSAGE
    */
    return $this->render('DocumentBundle:Panels:ActivationPanel.html.twig', Array(
      'filterForm' => $filterForm->createView(),
      'filterString' => $this->getFilterString($type,$markets,$airlines),
    ));
  }
}

这两种表单类型都在我的services.yml中定义:

  document.filter.form.type:
class: DocumentBundle\Form\Document\DocumentFilterType
arguments: ['@security.token_storage']
tags:
  - { name: form.type }

  document.deactivation.form.type:
    class: DocumentBundle\Form\Document\DocumentDeactivationType
    arguments: ['@security.token_storage']
    tags:
      - { name: form.type }

有谁可以帮助我? :)

防火墙:

firewalls:
    main:
        pattern: ^/
        form_login:
            provider: fos_userbundle
            csrf_token_generator: security.csrf.token_manager
            # if you are using Symfony < 2.8, use the following config instead:
            # csrf_provider: form.csrf_provider

        logout:       true
        anonymous:    true
        switch_user:  true
        user_checker: app.user_checker

1 个答案:

答案 0 :(得分:1)

DocumentDeactivationType 扩展 DocumentFilterType 。您(可能)复制/粘贴 private 属性tokenStorage以及 DocumentFilterType 中的构造函数。因此,当您将父表单类型类传递给子表单时,它无法访问tokenStorage。要解决此问题,您可以在 tokenStorage 中更改protected DocumentFilterType 的可见性,并删除__constructor()方法来自 tokenStorage 的<{1}}属性。