1

我想创建一个包含自引用实体集合的表单。

我需要一个表单来创建新产品,这个表单将有一个包含现有产品的选择字段(子)。

我有一个产品实体,这个实体包括一个子字段(子也是一个产品)。

产品实体:

/**
 * @var integer
 *
 * @ORM\Column(name="id", type="bigint", length=20)
 * @ORM\Id
 * @ORM\GeneratedValue(strategy="AUTO")
 */
protected $id;

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

/**
 * @var string
 *
 * @ORM\Column(name="manufacturer_reference", type="string", length=255, nullable=true)
 */
protected $manufacturer_reference;

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

/**
 * @var boolean
 *
 * @ORM\Column(name="is_salable", type="boolean", options={"default" = 1})
 */
protected $is_salable = 1;

/**
 * @var boolean
 *
 * @ORM\Column(name="is_active", type="boolean", options={"default" = 1})
 */
protected $is_active = 1;

/**
 * @ORM\ManyToOne(targetEntity="\Hexanet\Common\CatalogBundle\Entity\ProductCategory")
 * @ORM\JoinColumn(name="product_category_id", referencedColumnName="id", nullable=true)
 */
protected $product_category;

/**
 * @ORM\ManyToOne(targetEntity="\Hexanet\Common\CatalogBundle\Entity\Manufacturer")
 * @ORM\JoinColumn(name="manufacturer_id", referencedColumnName="id", nullable=true)
 */
protected $manufacturer;

/**
 * @ORM\ManyToMany(targetEntity="\Hexanet\Common\CatalogBundle\Entity\Product", mappedBy="parents" )
 */
protected $children;

/**
 * @ORM\ManyToMany(targetEntity="\Hexanet\Common\CatalogBundle\Entity\Product")
 * @ORM\JoinTable(name="product_to_product",
 *     joinColumns={@ORM\JoinColumn(name="child_product_id", referencedColumnName="id")},
 *     inverseJoinColumns={@ORM\JoinColumn(name="parent_product_id", referencedColumnName="id")}
 * )
 */
protected $parents;

/**
 * @ORM\OneToMany(targetEntity="\Hexanet\Common\CatalogBundle\Entity\ProductPrice", mappedBy="product" )
 */
protected $product_prices;

/**
 * @ORM\OneToMany(targetEntity="\Hexanet\Common\CatalogBundle\Entity\ProductPricePurchase", mappedBy="product")
 */
protected $product_prices_purchase;

/**
 * @ORM\OneToMany(targetEntity="\Hexanet\Common\CatalogBundle\Entity\ProductPriceCustom", mappedBy="product")
 */
protected $product_prices_custom;

/**
 * Get id
 *
 * @return integer
 */
public function getId()
{
    return $this->id;
}

/**
 * Set title
 *
 * @param string $title
 * @return Product
 */
public function setTitle($title)
{
    $this->title = $title;

    return $this;
}

/**
 * Get title
 *
 * @return string
 */
public function getTitle()
{
    return $this->title;
}

/**
 * Set product category
 *
 * @param \Hexanet\Common\CatalogBundle\Entity\ProductCategory $product_category
 * @return Product
 */
public function setProductCategory(\Hexanet\Common\CatalogBundle\Entity\ProductCategory $product_category = null)
{
    $this->product_category = $product_category;

    return $this;
}

/**
 * Get product category
 *
 * @return \Hexanet\Common\CatalogBundle\Entity\ProductCategory
 */
public function getProductCategory()
{
    return $this->product_category;
}

/**
 * Set resume
 *
 * @param string $resume
 * @return Product
 */
public function setResume($resume)
{
    $this->resume = $resume;

    return $this;
}

/**
 * Get resume
 *
 * @return string
 */
public function getResume()
{
    return $this->resume;
}

/**
 * Set manufacturer reference
 *
 * @param string $title
 * @return Product
 */
public function setManufacturerReference($ref)
{
    $this->manufacturer_reference = $ref;

    return $this;
}

/**
 * Get manufacturer reference
 *
 * @return string
 */
public function getManufacturerReference()
{
    return $this->manufacturer_reference;
}

/**
 * Set is salable
 *
 * @param boolean $active
 * @return Product
 */
public function setIsSalable($salable)
{
    $this->is_salable = $salable;

    return $this;
}

/**
 * Get is salable
 *
 * @return boolean
 */
public function getIsSalable()
{
    return $this->is_salable;
}

/**
 * Set is active
 *
 * @param boolean $active
 * @return Product
 */
public function setIsActive($active)
{
    $this->is_active = $active;

    return $this;
}

/**
 * Get is active
 *
 * @return boolean
 */
public function getIsActive()
{
    return $this->is_active;
}

/**
 * Set manufacturer
 *
 * @param $manufacturer
 * @return Product
 */
public function setManufacturer($manufacturer)
{
    $this->manufacturer = $manufacturer;

    return $this;
}

/**
 * Get manufacturer
 *
 */
public function getManufacturer()
{
    return $this->manufacturer;
}

/**
 * Constructor
 */
public function __construct()
{
    $this->parents = new \Doctrine\Common\Collections\ArrayCollection();
    $this->children = new \Doctrine\Common\Collections\ArrayCollection();
    $this->product_prices = new \Doctrine\Common\Collections\ArrayCollection();
    $this->product_prices_purchase = new \Doctrine\Common\Collections\ArrayCollection();
    $this->product_prices_custom = new \Doctrine\Common\Collections\ArrayCollection();
}

/**
 * Add child
 *
 * @param \Hexanet\Common\CatalogBundle\Entity\Product $product
 * @return Product
 */
public function addChild(\Hexanet\Common\CatalogBundle\Entity\Product $product)
{
    die(var_dump($product));
    $this->children[] = $product;

    return $this;
}

/**
 * Remove child
 *
 * @param \Hexanet\Common\CatalogBundle\Entity\Product $product
 */
public function removeChild(\Hexanet\Common\CatalogBundle\Entity\Product $product)
{
    $this->children->removeElement($product);
}

/**
 * Get children
 *
 * @return \Doctrine\Common\Collections\Collection
 */
public function getChildren()
{
    return $this->children;
}

/**
 * Add parent
 *
 * @param \Hexanet\Common\CatalogBundle\Entity\Product $product
 * @return Product
 */
public function addParent(\Hexanet\Common\CatalogBundle\Entity\Product $product)
{
    $this->parents[] = $product;

    return $this;
}

/**
 * Remove parent
 *
 * @param \Hexanet\Common\CatalogBundle\Entity\Product $price
 */
public function removeParent(\Hexanet\Common\CatalogBundle\Entity\Product $product)
{
    $this->parents->removeElement($product);
}

/**
 * Get parents
 *
 * @return \Doctrine\Common\Collections\Collection
 */
public function getParents()
{
    return $this->parents;
}

/**
 * Add product price
 *
 * @param \Hexanet\Common\CatalogBundle\Entity\ProductPrice $price
 * @return Product
 */
public function addProductPrice(\Hexanet\Common\CatalogBundle\Entity\ProductPrice $price)
{
    $this->product_prices[] = $price;

    return $this;
}

/**
 * Remove product price
 *
 * @param \Hexanet\Common\CatalogBundle\Entity\ProductPrice $price
 */
public function removeProductPrice(\Hexanet\Common\CatalogBundle\Entity\ProductPrice $price)
{
    $this->product_prices->removeElement($price);
}

/**
 * Get product prices
 *
 * @return \Doctrine\Common\Collections\Collection
 */
public function getProductPrices()
{
    return $this->product_prices;
}

/**
 * Add product price purchase
 *
 * @param \Hexanet\Common\CatalogBundle\Entity\ProductPricePurchase $price
 * @return Product
 */
public function addProductPricePurchase(\Hexanet\Common\CatalogBundle\Entity\ProductPricePurchase $price)
{
    $this->product_prices_purchase[] = $price;

    return $this;
}

/**
 * Remove product price purchase
 *
 * @param \Hexanet\Common\CatalogBundle\Entity\ProductPricePurchase $price
 */
public function removeProductPricePurchase(\Hexanet\Common\CatalogBundle\Entity\ProductPricePurchase $price)
{
    $this->product_prices_purchase->removeElement($price);
}

/**
 * Get product prices purchase
 *
 * @return \Doctrine\Common\Collections\Collection
 */
public function getProductPricesPurchase()
{
    return $this->product_prices_purchase;
}

/**
 * Add product price custom
 *
 * @param \Hexanet\Common\CatalogBundle\Entity\ProductPriceCustom $price
 * @return Product
 */
public function addProductPriceCustom(\Hexanet\Common\CatalogBundle\Entity\ProductPriceCustom $price)
{
    $this->product_prices_custom[] = $price;

    return $this;
}

/**
 * Remove product price custom
 *
 * @param \Hexanet\Common\CatalogBundle\Entity\ProductPriceCustom $price
 */
public function removeProductPriceCustom(\Hexanet\Common\CatalogBundle\Entity\ProductPriceCustom $price)
{
    $this->product_prices_custom->removeElement($price);
}

/**
 * Get product prices custom
 *
 * @return \Doctrine\Common\Collections\Collection
 */
public function getProductPricesCustom()
{
    return $this->product_prices_custom;
}}

对于表格我有这个:

class ProductType extends AbstractType{

public function buildForm(FormBuilderInterface $builder, array $options)
{
    $builder
        ->add('title')
        ->add('manufacturer_reference')
        ->add('resume')
        ->add('product_category', 'entity', array(
        'class' => 'HexanetCatalogBundle:ProductCategory',
        'property' => 'title',
        ))
        ->add('children', 'collection', array(
        'type' => new ProductChildrenType,
        'allow_add' => true));
}

public function setDefaultOptions(OptionsResolverInterface $resolver)
{
    $resolver->setDefaults(array(
        'data_class' => 'Hexanet\Common\CatalogBundle\Entity\Product'
    ));
}

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

问题就在那里,我不知道如何创建 ProductChildrenType 构建器:

class ProductChildrenType extends AbstractType{
public function buildForm(FormBuilderInterface $builder, array $options)
{
    $builder
        ->add('product', 'entity', array(
        'class' => 'HexanetCatalogBundle:Product',
        'property' => 'title',
        ));
}

public function setDefaultOptions(OptionsResolverInterface $resolver)
{
    $resolver->setDefaults(array(
        'data_class' => 'Hexanet\Common\CatalogBundle\Entity\Product'
    ));
}

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

->add('product', 'entity',...) 我有错误:

类“Hexanet\Common\CatalogBu​​ndle\Entity\Product”中不存在属性“product”、方法“getProduct()”和方法“isProduct()”。

谢谢帮助

4

1 回答 1

2

我有一个类似的商店案例,所以我可以在管理区域添加额外的产品,这样我就可以在结账时提供它们......我的工作伙伴和我昨天解决了这个问题,所以如果你仍然感兴趣,这里我们去.... 我们正在使用Symfony 2.6.x,我还没有在旧版本的 symfony 上测试过它。

->add('myExtras', 'collection', array(
            'type' => 'entity',
            'options' => array(
                'class'       => 'StoreBundle:Productos',
                'placeholder' => '-- Select an extra product --',
                'property' => 'name',
                'query_builder' => function (EntityRepository $er) use( $options ) {
                    return $er->createQueryBuilder('p')
                        ->where('p.asociable = :asociable')
                        ->andWhere('p.id != :selfid')
                        ->setParameters( array('adjuntable' => '1', 'selfid' => $options['selfid'] ));
                },
                'label' => 'Extra Product'
            ),
            'by_reference' => false,
            'allow_add'    => true,
            'allow_delete' => true
        ))

我们没有为“children”使用表单类型的集合,而是使用了“ entity ”类型的集合,并且我们使用了一个查询构建器来控制我们需要获得正确选项来显示的条件。

使用这个我们停止了你收到的消息......并且为了保存和删除关系,当我们添加孩子时,我们必须告诉孩子设置父母......并且首先删除相同的告诉孩子们从父母的列表中删除父母,然后从孩子列表中删除孩子......(在代码中更容易看到)

在实体中我必须收集myExtras(孩子)和imExtraOf(父母),所以当添加孩子时,我必须告诉孩子我正在接收对应的->addImExtraOf(我是你的父亲函数)......然后我们将产品添加到我们的额外列表中。对于删除,同样的,我们首先调用->removeImExtraOf,如果你不这样做,关系将不会被保存。

实体:

public function addMyExtra(Productos $extra)
{
    $extra->addImExtraOf($this);
    if( !$this->myExtras->contains($extra) ) {
        $this->myExtras[] = $extra;
    }


    return $this;
}

public function removeMyExtra(Productos $extra)
{
    $extra->removeImExtraOf($this);
    $this->myExtras->removeElement($extra);
}

orm 映射 (yml): (myExtras = children, imExtraOf = parents)

manyToMany:        
    myExtras:
        targetEntity: Productos
        cascade: [ persist ]
        mappedBy: imExtraOf
        inversedBy: null  
        joinTable:
            name: productos_has_productos
            joinColumns:
                -
                    name: extra_id
                    referencedColumnName: id
            inverseJoinColumns:
                -
                    name: base_id
                    referencedColumnName: id
        orderBy: null
    imExtraOf:
        targetEntity: Productos
        cascade: [ persist ]
        mappedBy: null
        inversedBy: myExtras  
        joinTable:
            name: productos_has_productos
            joinColumns:
                -
                    name: base_id
                    referencedColumnName: id
            inverseJoinColumns:
                -
                    name: extra_id
                    referencedColumnName: id
        orderBy: null

希望它可以帮助某人。

于 2015-08-08T13:56:17.087 回答