Symfony-如何将相关实体数据传递到实体字段';s的选择

Symfony-如何将相关实体数据传递到实体字段';s的选择,symfony,symfony-forms,Symfony,Symfony Forms,大家好 我有一个Product实体,它与ProductType实体有多对一的关系 我有基于“实体”字段类型的自定义ProductsType字段: class ProductsType extends AbstractType { /** * @param OptionsResolverInterface $resolver */ public function setDefaultOptions(OptionsResolverInterface $resol

大家好

我有一个Product实体,它与ProductType实体有多对一的关系

我有基于“实体”字段类型的自定义ProductsType字段:

class ProductsType extends AbstractType
{

    /**
     * @param OptionsResolverInterface $resolver
     */
    public function setDefaultOptions(OptionsResolverInterface $resolver)
    {

        $resolver->setDefaults(
            [
                'label' => 'oq.company.interest.label',
                'class' => 'OQReferenceBundle:Product',
                'required' => false,
                'expanded' => true,
                'multiple' => true,
                'choice_label' => 'name',
                'empty_value' => 'oq.reference.interest.choose',
                'query_builder' => function ($repository) {
                    $qb = $repository->createQueryBuilder('p');

                    $qb->leftJoin('OQReferenceBundle:ProductType', 'pt', 'WITH', 'p.productType = pt.id')
                        ->addOrderBy('pt.name', 'ASC')
                        ->addOrderBy('p.name', 'ASC');

                    return $qb;
                },
            ]
        );
    }

    /**
     * @return string
     */
    public function getName()
    {
        return 'oq_products_selector';
    }

    /**
     * @return string
     */
    public function getParent()
    {
        return 'entity';
    }
}
“oq_产品_选择器_小部件”代码:

{% block oq_products_selector_widget %}

    <div {{ block('widget_container_attributes') }}>

        {% for id, child in form %}
            <div class="oro-clearfix">
                {{ form_widget(child) }}
                <label for="{{ child.vars.id }}">
                    {{ choices[id].data.name }} ({{ choices[id].data.productType.name }})
                </label>
            </div>
        {% endfor %}

    </div>

{% endblock %}
{%block oq_products_selector_widget%}
{%表示id,子项形式为%}
{{form_widget(child)}
{{choices[id].data.name}({{choices[id].data.productType.name})
{%endfor%}
{%endblock%}
但当我尝试渲染表单时,有一个例外:

无法访问空变量上的属性(“id”)

据我所知,相关实体数据未传递到choice数据数组,无法通过
choices[id].data.productType.name来显示


如何将这些数据传递给choice?

嗯,我解决了这个问题

我假设entity字段类型为choice数组中没有相关实体的对象添加了水合物。因此,我将自定义字段类型父项切换为“choice”,然后使用EntityManager和standart repository的
findAll
方法接收所有用于选择的实体,并从所有链接实体(ProductType)中获取数据,没有任何问题

代码

class ProductsType extends AbstractType
{

    /** @var EntityManager */
    protected $em;

    public function __construct(EntityManager $em)
    {
        $this->em = $em;
    }

    /**
     * {@inheritdoc}
     */
    public function buildForm(FormBuilderInterface $builder, array $options)
    {
        $builder->addModelTransformer(new ProductsTransformer($this->em));
    }

    /**
     * @param OptionsResolverInterface $resolver
     */
    public function setDefaultOptions(OptionsResolverInterface $resolver)
    {

        $choices = array();
        $choicesAttrs = array();

        /** @var ProductRepository $repo */
        $repo = $this->em->getRepository("OQReferenceBundle:Product");
        if ($products = $repo->getProductsSortedByProductType()) {
            /** @var Product $product */
            foreach ($products as $product) {
                $choices[$product->getId()] = $product->getName();
                $choicesAttrs[$product->getName()] = array('data-product-type' => $product->getProductType()->getName());
            }
        }

        $resolver->setDefaults(
            [
                'label' => 'oq.company.interest.label',
                'required' => false,
                'expanded' => true,
                'multiple' => true,
                'empty_value' => 'oq.reference.interest.choose',
                'choices' => $choices,
                'choice_attr' => $choicesAttrs,
            ]
        );
    }

    /**
     * @return string
     */
    public function getName()
    {
        return 'oq_products_selector';
    }

    /**
     * @return string
     */
    public function getParent()
    {
        return 'choice';
    }
}
正如你们所看到的,我得到了所有选择的实体,并将它们放在数组中。然后我获取所有相关实体的名称,并将它们放入另一个数组中。并将此数组传递给带有
'choice\u attr'=>$choicesAttrs
参数的选项

之后,我可以访问这些额外的数据

{% block oq_products_selector_widget %}

    <div {{ block('widget_container_attributes') }}>
        <div class="horizontal">

            {% set productType = '' %}

            {% for id, child in form %}
                <div class="oro-clearfix">

                    {% if productType != child.vars.attr['data-product-type'] %}
                        {% set productType = child.vars.attr['data-product-type'] %}
                        <div style="margin-bottom: 6px;">
                            <strong>{{ productType }}</strong>
                        </div>
                    {% endif %}

                    {{ form_widget(child) }}
                    <label for="{{ child.vars.id }}">
                        {{ child.vars.label }}
                    </label>
                </div>
            {% endfor %}

        </div>
    </div>

{% endblock %}
{%block oq_products_selector_widget%}
{%set-productType=''%}
{%表示id,子项形式为%}
{%if productType!=child.vars.attr['data-product-type']%}
{%set-productType=child.vars.attr['data-product-type']%}
{{productType}}
{%endif%}
{{form_widget(child)}
{{child.vars.label}
{%endfor%}
{%endblock%}

嗯,我解决了那个问题

我假设entity字段类型为choice数组中没有相关实体的对象添加了水合物。因此,我将自定义字段类型父项切换为“choice”,然后使用EntityManager和standart repository的
findAll
方法接收所有用于选择的实体,并从所有链接实体(ProductType)中获取数据,没有任何问题

代码

class ProductsType extends AbstractType
{

    /** @var EntityManager */
    protected $em;

    public function __construct(EntityManager $em)
    {
        $this->em = $em;
    }

    /**
     * {@inheritdoc}
     */
    public function buildForm(FormBuilderInterface $builder, array $options)
    {
        $builder->addModelTransformer(new ProductsTransformer($this->em));
    }

    /**
     * @param OptionsResolverInterface $resolver
     */
    public function setDefaultOptions(OptionsResolverInterface $resolver)
    {

        $choices = array();
        $choicesAttrs = array();

        /** @var ProductRepository $repo */
        $repo = $this->em->getRepository("OQReferenceBundle:Product");
        if ($products = $repo->getProductsSortedByProductType()) {
            /** @var Product $product */
            foreach ($products as $product) {
                $choices[$product->getId()] = $product->getName();
                $choicesAttrs[$product->getName()] = array('data-product-type' => $product->getProductType()->getName());
            }
        }

        $resolver->setDefaults(
            [
                'label' => 'oq.company.interest.label',
                'required' => false,
                'expanded' => true,
                'multiple' => true,
                'empty_value' => 'oq.reference.interest.choose',
                'choices' => $choices,
                'choice_attr' => $choicesAttrs,
            ]
        );
    }

    /**
     * @return string
     */
    public function getName()
    {
        return 'oq_products_selector';
    }

    /**
     * @return string
     */
    public function getParent()
    {
        return 'choice';
    }
}
正如你们所看到的,我得到了所有选择的实体,并将它们放在数组中。然后我获取所有相关实体的名称,并将它们放入另一个数组中。并将此数组传递给带有
'choice\u attr'=>$choicesAttrs
参数的选项

之后,我可以访问这些额外的数据

{% block oq_products_selector_widget %}

    <div {{ block('widget_container_attributes') }}>
        <div class="horizontal">

            {% set productType = '' %}

            {% for id, child in form %}
                <div class="oro-clearfix">

                    {% if productType != child.vars.attr['data-product-type'] %}
                        {% set productType = child.vars.attr['data-product-type'] %}
                        <div style="margin-bottom: 6px;">
                            <strong>{{ productType }}</strong>
                        </div>
                    {% endif %}

                    {{ form_widget(child) }}
                    <label for="{{ child.vars.id }}">
                        {{ child.vars.label }}
                    </label>
                </div>
            {% endfor %}

        </div>
    </div>

{% endblock %}
{%block oq_products_selector_widget%}
{%set-productType=''%}
{%表示id,子项形式为%}
{%if productType!=child.vars.attr['data-product-type']%}
{%set-productType=child.vars.attr['data-product-type']%}
{{productType}}
{%endif%}
{{form_widget(child)}
{{child.vars.label}
{%endfor%}
{%endblock%}