我正在用Symfony2和Doctrine2创建一个电子商务 bundle 包。我将EAV方法应用于产品功能,并针对无限功能使用产品值(value)。为此,我有三个基本实体:Product,FeatureKind和FeatureValues。

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

  • 问题是我需要将FeatureType作为标签,并将其作为产品表单中的选择字段使用各种值。我已经设法在产品表单中获取了特征种类和相关的值,但是我不知道如何将它们转换为选择字段。

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

    注意:我已从代码中删除了多余的内容以使其简短。

    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,它仍将为循环的最后一次迭代仅创建一个表单字段。

    我没有选择。

    最佳答案

    您当前的结构无法完成您想做的事情。让我尝试解释一下:FeatureKind与FeatureValue有一对多的关系。这意味着您可以使用“颜色”种类,其值可以为“红色”,“粉红色”等。这很好。但是您的产品实体具有FeatureKind对象的集合,因此它可以具有诸如“颜色”,“大小”等的列表。但是(这是最重要的部分),它无法为任何对象指定特定的值在这些种类中:没有一种属性可以保存每种种类的特定值。我希望您能理解这一点,这有点难以解释。

    你需要做什么:

    照原样定义FeatureValue和FeatureKind类。

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

    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;
    }
    

    该实体处理成对的kind:value,例如color:red

    最后,您的产品实体具有这种新类型的属性:
    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 question答案中给出的说明类似的操作

    09-12 22:12