9

Symfony2.1.3-devとDoctrine2.3の使用

ユーザーが返されたデータのセットをフィルタリングするための複数のオプションを提供するフォームを作成しようとしています(Entity\EngineCodes)。フォームは、1つのテキスト入力フィールド(id)と3つの選択フィールド(、、)moduletype構成されていますstatus。Symfony2 entityform_typeを使用して、EngineCodesエンティティから3つの選択フィールドの値を生成しようとしています。

選択フィールドの任意の3つの組み合わせを使用してテーブルをフィルタリングしたいので。2.1のドキュメントに基づいて、FormType(EngineCodesFilterType)を作成し、3つのフォームフィールドをステートメントでentity入力query_builderするように設定して、各フィールドに一意の値のセットを返すことにしました。

残念ながら、フォローエラーが発生し、オブジェクトではなく配列が返される理由が正確にはわかりません。

    The form's view data is expected to be an instance of class
    Vendor\IndexBundle\Entity\EngineCodes, but is a(n) array.
    You can avoid this error by setting the "data_class" option
    to null or by adding a view transformer that transforms a(n)
    array to an instance of Vendor\IndexBundle\Entity\EngineCodes.

に設定data_classするとnull、次のエラーが発生します。

    A "__toString()" method was not found on the objects of type
    "Vendor\IndexBundle\Entity\EngineCodes" passed to the choice
    field. To read a custom getter instead, set the option
    "property" to the desired property path.

私はまだこれらのSymfony2の機能を学んでいるので、私の目標は、構造とフォーマットの点で2.1ドキュメントと可能な限り一致させることでした。

コントローラ内の機能は次のとおりです。

public function displayAction() {

    // ...

    $entity = $this->getDoctrine()->getEntityManager()
        ->getRepository('VendorIndexBundle:EngineCodes')
        ->findAll();

    // ...

    $form = $this->createForm(new EngineCodesFilterType(), $entity);

    // ...

    return $this->render(
        'VendorIndexBundle::layout.html.twig',
        array(
            'entity'  => $entity,
            'form'    => $form->createView(),));

フォームタイプは次のとおりです。

class EngineCodesFilterType extends AbstractType
{
    public function buildForm(FormBuilderInterface $builder, array $options)
    {
        $builder->add(
            'id',
            'integer',
            array(
                'label' => 'Code ID',));
        $builder->add(
            'status',
            'entity',
            array(
                'label' => 'Code Status',
                'class' => 'VendorIndexBundle:EngineCodes',
                'query_builder' => function(EntityRepository $er)
                    {
                        return $er->createQueryBuilder('u')
                            ->select('u.status')
                            ->add('groupBy', 'u.status');
                    },
                'multiple' => true,));
        $builder->add(
            'type',
            'entity',
            array(
                'label' => 'Code Type',
                'class' => 'VendorIndexBundle:EngineCodes',
                'query_builder' => function(EntityRepository $er)
                    {
                        return $er->createQueryBuilder('u')
                            ->select('u.type')
                            ->add('groupBy' ,'u.type');
                    },
                'multiple' => true,));
        $builder->add(
            'module',
            'entity',
            array(
                'label' => 'Code Module',
                'class' => 'VendorIndexBundle:EngineCodes',
                'query_builder' => function(EntityRepository $er)
                    {
                        return $er->createQueryBuilder('u')
                            ->select('u.module')
                            ->add('groupBy', 'u.module');
                    },
                'multiple' => true,));
    }

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

    public function setDefaultOptions(OptionsResolverInterface $resolver)
    {
        $resolver->setDefaults(
            array(
                'data_class'        => 'Vendor\IndexBundle\Entity\EngineCodes',
              /*'data_class'        => null,*/
                'validation_groups' => 'filter',));
    }
}

そしてここにVendor\Entity\EngineCodesクラスがあります:

/**
 * Vendor\IndexBundle\Entity\EngineCodes
 *
 * @ORM\Table(name="engine_codes")
 * @ORM\Entity(repositoryClass="Vendor\IndexBundle\Entity\EngineCodesRepository")
 * @UniqueEntity(fields="id", message="ID already in use! Enter a unique ID for the code.")
 */
class EngineCodes
{
    /**
     * @var integer $id
     *
     * @ORM\Column(name="id", type="integer", nullable=false, unique=true)
     * @ORM\Id
     * @Assert\NotBlank(message="ID cannot be blank!")
     * @Assert\Regex(pattern="/^\d+$/", match=true, message="ID must be an integer!")
     * @Assert\MinLength(limit=8, message="ID must be 8 numbers in length!")
     * @Assert\MaxLength(limit=8, message="ID must be 8 numbers in length!")
     */
    private $id;

    /**
     * @var string $token
     *
     * @ORM\Column(name="token", type="string", length=255, nullable=false, unique=true)
     */
    private $token;

    /**
     * @var boolean $status
     *
     * @ORM\Column(name="status", type="integer", nullable=false)
     * @Assert\NotBlank(message="Status cannot be blank!")
     */
    private $status;

    /**
     * @var string $module
     *
     * @ORM\Column(name="module", type="string", length=255, nullable=false)
     * @Assert\NotBlank(message="Module cannot be blank!")
     */
    private $module;

    /**
     * @var string $submodule
     *
     * @ORM\Column(name="submodule", type="string", length=255, nullable=false)
     * @Assert\NotBlank(message="Submodule cannot be blank!")
     */
    private $submodule;

    /**
     * @var string $type
     *
     * @ORM\Column(name="type", type="string", length=255, nullable=false)
     * @Assert\NotBlank(message="Type cannot be blank!")
     */
    private $type;

    /**
     * @var string $description
     *
     * @ORM\Column(name="description", type="text", nullable=false)
     * @Assert\NotBlank(message="Description cannot be blank!")
     */
    private $description;

    /**
     * @var string $title
     *
     * @ORM\Column(name="title", type="string", length=255, nullable=false)
     * @Assert\NotBlank(message="Title cannot be blank!")
     */
    private $title;

    /**
     * @var string $definition
     *
     * @ORM\Column(name="definition", type="text", nullable=true)
     */
    private $definition;

    /**
     * @var string $color
     *
     * @ORM\Column(name="color", type="string", length=10, nullable=true)
     */
    private $color;

    /**
     * @var \DateTime $createTimestamp
     *
     * @ORM\Column(name="create_timestamp", type="datetime", nullable=false)
     */
    private $createTimestamp;

    /**
     * @var Accounts
     *
     * @ORM\ManyToOne(targetEntity="Accounts")
     * @ORM\JoinColumns({
     *   @ORM\JoinColumn(name="create_account_fk", referencedColumnName="id")
     * })
     */
    private $createAccountFk;


    // getters and setters ...

    /**
     * Set createAccountFk
     *
     * @param Vendor\IndexBundle\Entity\Accounts $createAccountFk
     * @return EngineCodes
     */
    public function setCreateAccountFk(\Vendor\IndexBundle\Entity\Accounts $createAccountFk = null)
    {
        $this->createAccountFk = $createAccountFk;

        return $this;
    }

    /**
     * @ORM\PrePersist
     */
    public function setCreateTimestampValue()
    {
        $this->createTimestamp = new \DateTime();
    }
}
4

2 に答える 2

14

最初の問題は$entity、単一のエンティティではなく、エンティティの配列(findAll()メソッドによって返されるもの)であるということです。フォームタイプを定義したときに、エンティティからフォームを作成することを期待していると言いました(これがdata_classオプションの目的です)。そのため、最初のエラーが発生します。

nullに設定data_classすると、フォームがエンティティから作成されることを期待していないことを意味するため、エンティティの配列を受け入れ、文句を言うことはありません。しかし、なぜエンティティの配列をフォームタイプに渡すのですか?これは、エンティティをフィルタリングするために4つの可能な値を選択できる単なるフィルターフォームです。これには、基礎となるデータとしてエンティティの配列は必要ありません。コード、タイプ、ステータスフィールドの値を取得するために必要だと思われる場合は、クエリビルダーで既にフェッチされているため、そうではありません。したがって、コントローラーコードは次のようになります。

public function displayAction() {

// ...

$entity = $this->getDoctrine()->getEntityManager()
    ->getRepository('VendorIndexBundle:EngineCodes')
    ->findAll();

// ...

$form = $this->createForm(new EngineCodesFilterType());

// ...

return $this->render( // ...

次に、3つのフォームフィールドを追加し、それぞれがエンティティリストから選択できるため、もう1つのエラーが発生します。しかし、このエンティティをどのように「表示」しますか?symfonyはエンティティを表すためにどのフィールドを表示すべきかわからないので、このエラーをスローします。

このエラーは、EngineCodesクラスに__toString()メソッドを追加することで修正できます。このメソッドは、「ねえ、これはこのクラスを表示したい方法です」とだけ言っていますが、エラーはスローされませんが、 3つのフィールドは、異なるプロパティを表示したいと考えています。

別の解決策はproperty、フォームフィールドのオプションを使用して、データの表示に使用する基になるオブジェクトのプロパティを指定することです。

例えば:

$builder->add(
        'status',
        'entity',
        array(
            'label' => 'Code Status',
            'class' => 'VendorIndexBundle:EngineCodes',
            'property' => 'status'
            'query_builder' => function(EntityRepository $er)
                {
                    return $er->createQueryBuilder('u')
                        ->select('u.status')
                        ->add('groupBy', 'u.status');
                },
            'multiple' => true,));
于 2012-09-22T07:26:23.533 に答える
11

「status」、「type」、「module」エンティティタイプのプロパティオプションが欠落しているだけです。

財産

タイプ:文字列

これは、エンティティをHTML要素のテキストとして表示するために使用する必要があるプロパティです。空白のままにすると、エンティティオブジェクトは文字列にキャストされるため、__ toString()メソッドが必要です。

于 2012-09-22T07:17:27.590 に答える