我正在使用Symfony2和Doctrine2创建一个电子商务包。 我正在应用EAV方法来获得无限功能的产品功能和产品价值。 为此,我有三个基本实体:Product,FeatureKind和FeatureValues。

  • FeatureKind与FeatureValues连接,具有OneToMany单向关系。
  • 产品通过ManyToMany关系连接到FeatureKind。

问题是我需要FeatureType作为标签,它的各种值作为产品形式的选择字段。 我已设法在产品表单中获取featurekind和相关值,但我不知道如何将它们转换为选择字段。

以下是所有三个实体,控制器和表单代码以及我的代码的结果。

注意:我已经从代码中删除了额外的东西以保持简短。

Product.php

namespace Webmuch\ProductBundle\Entity;

/**
 * @ORM\Table()
 * @ORM\Entity
 */
class Product
{
    /**
     * @ORM\Column(name="id", type="integer")
     * @ORM\Id
     * @ORM\GeneratedValue(strategy="AUTO")
     */
    private $id;

    /**
     * @ORM\Column(name="title", type="string", length=255)
     */
    private $title;

    /**
     * @ORM\ManyToMany(targetEntity="FeatureKind", inversedBy="product", cascade={"persist"})
     * @ORM\JoinTable(name="product_featurekind")
     **/
    private $featurekind;
}

FeatureKind.php

namespace Webmuch\ProductBundle\Entity;

/**
 * @ORM\Table(name="feature_kind")
 * @ORM\Entity
 */
class FeatureKind
{
    /**
     * @ORM\Id
     * @ORM\Column(name="id", type="integer")
     * @ORM\GeneratedValue(strategy="AUTO")
     */
    protected $id;

    /**
     * @ORM\Column(name="name", type="string", length=50)
     */
    protected $name;

    /**
     * @ORM\ManyToMany(targetEntity="FeatureValue")
     * @ORM\JoinTable(name="feature_kind_value",
     *      joinColumns={@ORM\JoinColumn(name="kind_id", referencedColumnName="id")},
     *      inverseJoinColumns={@ORM\JoinColumn(name="value_id", referencedColumnName="id", unique=true)}
     *      )
     **/
    protected $values;   
}

FeatureValue.php

namespace Webmuch\ProductBundle\Entity;

/**
 * @ORM\Table()
 * @ORM\Entity
 */
class FeatureValue
{
    /**
     * @ORM\Column(name="id", type="integer")
     * @ORM\Id
     * @ORM\GeneratedValue(strategy="AUTO")
     */
    protected $id;

    /**
     * @ORM\Column(name="value", type="string", length=100)
     */
    protected $value;
}

ProductController.php

public function newAction(Request $request)
{
    $entity = new Product();
    $em = $this->getDoctrine()->getEntityManager();
    $features = $em->getRepository('ProductBundle:FeatureKind')->findAll();

    foreach($features as $feature)
    {
        $featurekind = new FeatureKind();
        $featurekind->setTitle($feature->getTitle());
        foreach($feature->getValue() as $value ){
            $featurekind->getValue()->add($value);
        }
        $entity->getFeaturekind()->add($featurekind);   
    }

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

     if ('POST' === $request->getMethod()) {
        $form->bindRequest($request);
        if ($form->isValid()) {
            $em->persist($entity);
            $em->flush();

            return $this->redirect($this->generateUrl('product_show', array(
                'id' => $entity->getId()
            )));
        }
    }
    return $this->render('ProductBundle:Product:new.html.twig', array(
       'form'   => $form->createView()
    ));
}

ProductType.php

namespace Webmuch\ProductBundle\Form;

use Symfony\Component\Form\AbstractType;
use Symfony\Component\Form\FormBuilder;

class ProductType extends AbstractType
{
    public function buildForm(FormBuilder $builder, array $options)
    {
        $builder
            ->add('featurekind', 'collection', array('type' => new FeatureKindType()))
            ->getForm();
        }

    public function getDefaultOptions(array $options)
    {
        return array(
            'data_class' => 'Webmuch\ProductBundle\Entity\Product',
            'required' => true
        );
    }

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

FeatureKindType.php

namespace Webmuch\ProductBundle\Form;

class FeatureKindType extends AbstractType
{
    public function buildForm(FormBuilder $builder, array $options)
    {
        $builder
            ->add('title')
            ->add('value','collection', array(
                                               'type' => new FeatureValueType(),
                                               'allow_add'=>true))
            ->getForm();
    }

    public function getDefaultOptions(array $options)
    {
        return array(
            'data_class' => 'Webmuch\ProductBundle\Entity\FeatureKind',
        );
    }

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

这是我的表格结果。

编辑:

经过几天的工作,我现在坚持使用一系列简单的功能及其各自的多个值:

Array
(
    [Color] => Array
        (
            [Red] => Red
            [Green] => Green
        )

    [Size] => Array
        (
            [Large] => Large
            [Medium] => Medium
            [Small] => Small
        )

    [Sleeve Style] => Array
        (
            [Half Sleeved] => Half Sleeved
            [Full Sleeved] => Full Sleeved
            [Cut Sleeves] => Cut Sleeves
        )

)

我试图按如下方式创建表单: $ this-> choices包含数组。

$builder
    ->add('name')
    ->add('slug')
    ->add('active')
;

foreach ($this->choices as $choice) {
    $builder->add('featurekind', 'choice', array(
        'required' => 'false',
        'choices' => $choice,
        'empty_value' => 'Choose an option',
        'empty_data'  => null
    ));
}

$builder->getForm();

以上内容不适用于属性$ featurekind 我收到错误:

Notice: Object of class Doctrine\Common\Collections\ArrayCollection could not be converted to int in /vagrant/project/vendor/symfony/symfony/src/Symfony/Component/Form/Extension/Core/ChoiceList/ChoiceList.php line 457

虽然如果表单字段附加到任何未关联的属性,例如:$ name,它仍然只为循环的最后一次迭代创建一个表单字段。

我没有选择。

#1楼 票数:3

您当前的结构无法完成您想要做的事情。 让我试着解释一下:FeatureKind与FeatureValue有一对多的关系。 这意味着您可以使用“颜色”类型,其值可以是“红色”,“粉红色”等。这很好。 但是你的产品实体有一个FeatureKind对象的集合,所以它可以有一个像“颜色”,“大小”等的列表......但是(这是最重要的部分)它无法将任何特定值赋予任何特定值。这些种类:没有属性可以保持每种类型的特定价值。 我希望你能解决这个问题,这有点难以解释。

你需要做什么:

按原样定义FeatureValue和FeatureKind类。

定义一个新实体,它处理产品的种类和价值之间的关联:

namespace Webmuch\ProductBundle\Entity;

/**
 * @ORM\Table()
 * @ORM\Entity
 */
class FeatureKindValue
{
    /**
     * @ORM\Id
     * @ORM\Column(name="id", type="integer")
     * @ORM\GeneratedValue(strategy="AUTO")
     */
    protected $id;

    /**
     * @ManyToOne(targetEntity="Product", inversedBy="features")
     **/
    private $product;

    /**
     * @ORM\ManyToOne(targetEntity="FeatureKind")
     **/
    protected $kind;   

    /**
     * @ORM\ManyToOne(targetEntity="FeatureValue")
     **/
    protected $value;   
}

此实体处理对类:值,例如颜色:红色

最后,您的产品实体具有此新类型的属性:

namespace Webmuch\ProductBundle\Entity;

/**
 * @ORM\Table()
 * @ORM\Entity
 */
class Product
{
    /**
     * @ORM\Column(name="id", type="integer")
     * @ORM\Id
     * @ORM\GeneratedValue(strategy="AUTO")
     */
    private $id;

    /**
     * @ORM\Column(name="title", type="string", length=255)
     */
    private $title;

    /**
     * @ORM\OneToMany(targetEntity="FeatureKindValue", mappedBy="product")
     **/
    private $features;
}

然后,为了根据需要显示表单,请执行类似于此stackoverflow 问题的答案中给出的说明

#2楼 票数:1

这种东西可能很棘手,但你可以在FeatureKindType类中使用这种方法

public function buildForm(FormBuilderInterface $builder, array $options)
{
    $builder->addEventListener(
        FormEvents::PRE_SET_DATA,
        function (DataEvent $event) use ($builder) {
            /* @var FormBuilderInterface $builder */
            $form = $event->getForm();
            /* @var FeatureKind $data */
            $data = $event->getData();
            if ($data !== null) {
                $form->add(
                    $builder->getFormFactory()->createNamed(
                        'values',
                        'entity',
                        null,
                        array(
                            'label' => $data->getName(),
                            'class' => 'WebmuchProductBundle:FeatureValue',
                        )
                    )
                );
            }
        }
    );
}

请注意,我没有尝试发布表单并在您的案例中保存实体,但表单现在将FeatureKind的名称作为标签和包含相应FeatureKindValues的下拉列表选择。

我在我的一个项目中使用这种方法,它对我有用。

  ask by Aayush translate from so

未解决问题?本站智能推荐:

1回复

Symfony:具有灵活关系的实体及其(子)表单-如何设计?

我有一个具有基本信息的User -Entity。 User应该能够在配置文件中共享更详细的数据。 不同的User有不同的ProfileSet 。 在此示例中,我尝试使其简单: ProfileSet_A是具有个人信息的配置文件, ProfileSet_B存储匿名数据。 一个User
1回复

Symfony2 - 在事件之间传递数据

我需要的 我必须构建一个允许输入非常简单的工资单的模块。 代表这个的类是PayStub和Detail ,它们是POPO和持久性的。 此外, Detail必须与Fee相平衡, Fee又属于Tariff类别。 因此, Detail信息包含有关正在支付的Fee信息。 为了使事情稍微复
1回复

具有EAV返回值的Symfony2.1

我有三个实体: 1.功能 2.价值 3.产品 我在获得“产品价值”时没有提及它的功能。 我正在尝试根据功能获取价值,但是我却做不到。我不知道该怎么做? 特征: 值: 产品: 由于英语薄弱,我不解释更多。 我想要的示例: “我想选
1回复

如何获取Symfony 2表单以从动态值返回实体

好的,这里是我要做什么的快速概述。 我有一个与“ ClientDomain”实体有关系的“ Client”实体。 我需要有一个表格,该表格将显示给定客户端的所有ClientDomain列表。 在控制器中,我知道我需要过滤哪些客户端,但是不确定如何将该信息传递给formBuilder。
1回复

在Symfony2表单中将函数返回值用于options选项

我有这个Symfony2表格: 我有这个代码: 我需要将$choices用作choices值,如何实现呢?
3回复

以Symfony2形式

我有两张桌子 和 我正在使用Symfony2表单创建表单。 我想知道如何将所有城市列为<select>表单元素的<option> ,以便为用户xyz生成以下标记。 目前,我的控制器中有类似这样的代码,
1回复

symfony 2验证形式超过10个长度值bigint?

我在MySQL数据库(bigint 20)中将值设置为bigint 。 当我以超过10个字符的形式设置值时,例如“ 1234567890123”; 我收到一条错误消息,指出: This value is not valid 。 User.orm.yml 查看表格: MyS
2回复

基于Symfony2中的其他字段值对字段进行条件验证

所以这是场景:我有一个单选按钮组。 基于它们的价值,我应该或不应该验证其他三个字段(它们是空白的,它们是否包含数字等)。 我可以以某种方式将所有这些值传递给约束,并在那里进行比较吗? 或者直接在控制器中回调是解决此问题的更好方法? 一般来说,这种情况下的最佳做法是什么?