如何在Symfony

时间:2015-08-31 23:31:00

标签: php forms symfony

我正在开发一个有很多查询表格的项目 有许多字段“集合”将用于多个表单。 我想使用子表单,但是我还没有能够使用它。

我一直得到这个例外:

  

表单的视图数据应该是标量,数组或\ ArrayAccess实例的类型,但是是SiteBundle \ Entity \ EntityB类的实例。 You can avoid this error by setting the "data_class" option to "SiteBundle\Entity\EntityB"或添加一个视图转换器,将SiteBundle \ Entity \ EntityB类的实例转换为标量,数组或\ ArrayAccess的实例。

我已将问题分离为一个比我的实际应用程序简单得多的示例,并在此处提供示例的源代码。示例是EntityB类的来源。

我的子表单中有一个选择字段,如果我将该字段注释掉,则异常消失,所以我猜它与此有关。

主要表格背后的实体:

// src/SiteBundle/Entity/EntityA.php

namespace SiteBundle\Entity;

class EntityA
{
  private $customerCode;
  private $customerName;
  private $b; // (an instance of EntityB)

  public function getCustomerCode()
  {
    return $this->customerCode;
  }

  public function setCustomerCode( $customerCode )
  {
    $this->customerCode = $customerCode;
    return $this;
  }

  public function getCustomerName()
  {
    return $this->customerName;
  }

  public function setCustomerName( $customerName )
  {
    $this->customerName = $customerName;
    return $this;
  }

  public function getB()
  {
    return $this->b;
  }

  public function setB( $b )
  {
    $this->b = $b;
    return $this;
  }
}

主要表格

// src/SiteBundle/Form/Type/FormA.php

namespace SiteBundle\Form\Type;

use Symfony\Component\Form\AbstractType;
use Symfony\Component\Form\FormBuilderInterface;
use Symfony\Component\OptionsResolver\OptionsResolver;

class FormA extends AbstractType
{
  public function buildForm( FormBuilderInterface $builder, array $options )
  {
    $builder
      ->add( 'customerCode', 'text', [ 'label' => 'Customer code:', ] )
      ->add( 'customerName', 'text', [ 'label' => 'Customer name:' ] )
      ->add( 'b', 'FormB', [ 'label' => 'Option:' ] );
  }


  public function configureOptions( OptionsResolver $resolver )
  {
    $resolver->setDefaults( [ 'data_class' => 'SiteBundle\Entity\EntityA' ] );
  } // configureOptions()


  public function getName()
  {
    return 'FormA';
  } // getName()
}

子表单背后的实体

// src/SiteBundle/Entity/entityB.php

namespace SiteBundle\Entity;    

class EntityB
{
  private $opt1 = false;
  private $opt2 = false;
  private $opt3 = false;
  private $start;
  private $end;

  public function getOption()
  {
    return $this;
  }

  public function setOption( $val )
  {
    switch( $val )
    {
      case 1:
        $this->opt1 = true;
        $this->opt2 = false;
        $this->opt3 = false;
        break;

      case 2:
        $this->opt2 = true;
        $this->opt1 = false;
        $this->opt3 = false;
        break;

      case 3:
        $this->opt3 = true;
        $this->opt1 = false;
        $this->opt2 = false;
        break;
    }
    return $this;
  }

  public function getStart()
  {
    return $this->start;
  }

  public function setStart( $start )
  {
    $this->start = $start;
    return $this;
  }

  public function getEnd()
  {
    return $this->end;
  }

  public function setEnd( \DateTime $end )
  {
    $this->end = $end;
    return $this;
  }
}

子表格

// src/SiteBundle/Form/Type/FormB.php

namespace SiteBundle\Form\Type;

use Symfony\Component\Form\AbstractType;
use Symfony\Component\Form\FormBuilderInterface;
use Symfony\Component\OptionsResolver\OptionsResolver;

class FormB extends AbstractType
{
  public function buildForm( FormBuilderInterface $builder, array $options )
  {
    $builder
      ->add( 'option',
             'choice',
             [
               'expanded' => true,
               'multiple' => false,
               'label'    => 'Option:',
               'choices'  =>
                 [
                   '1'  => 'One',
                   '2'  => 'Two',
                   '3'  => 'Three'
                 ],
               'attr' => [ 'class' => 'checkbox-inline' ],
             ] )
      ->add( 'start',
             'date',
             [
               'label' => 'Start date:',
               'widget' => 'single_text',
             ] )
      ->add( 'end',
             'date',
             [
               'label' => 'End date:',
               'widget' => 'single_text',
             ] );
  }

  public function ConfigureOptions( OptionsResolver $resolver )
  {
    $resolver->setDefaults( [ 'data_class' => 'SiteBundle\Entity\EntityB' ] );
  }

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

services.yml中的条目

 # src/SiteBundle/Resources/config/service.yml

 form.a:
    class:  SiteBundle\Form\Type\FormA
    tags:
      - { name: form.type, alias: FormA }

  form.b:
    class:  SiteBundle\Form\Type\FormB
    tags:
      - { name: form.type, alias: FormB }

控制器操作方法

  /**
   * @route( "/debug", name="debug" )
   */
  public function debugAction( Request $request )
  {
    $b = new EntityB();
    $b->setOption( 1 )
      ->setStart( new \DateTime( 'today' ))
      ->setEnd( new \DateTime( 'today + 7 days' ));

    $a = new EntityA();
    $a->setCustomerCode( '1234' )
      ->setCustomerName( 'Test Customer' )
      ->setB( $b );

    $form = $this->createForm( 'FormA', $a );
    $form->handleRequest( $request );
    if( $form->isValid() )
    {
      $this->getFlashbag()->add( 'info', "Form successfully validated" );
    }

    $vars =
      [
        'form' => $form->createView()
      ];
    return $this->render( 'SiteBundle:debug:form.html.twig', $vars );

  } // debugAction()

我在EntityB::ConfigureOptions()中设置了data_class参数,这使得上面的异常消息的突出显示部分更加混乱。

我怀疑我错过了一些相当基本的东西,但不知道是什么。

环境:
- PHP 5.5.9
- Symfony 2.7.3
我今天跑了composer self-updatecomposer update,以确保我是最新的。

1 个答案:

答案 0 :(得分:0)

原来,@ Cerad的第一条评论是正确的。

  

formb期望实体b有一个名为option的属性。 EntityB :: getOption返回$ this,解释了错误。调整getOption以返回实际的缩放器值。

我不知道为什么我的初步测试失败了,但后来的测试成功了。

我必须说,例外的措辞是非常误导和混淆的。