Symfony2表单集合字段未显示

时间:2014-02-25 09:58:26

标签: php symfony

我会解释我想要做的事情。

我有以下实体,经销商品牌和类型。

1经销商可以关联许多品牌,每个关系也会关联一个类型,这就是为什么与中间表的manyToMany关系。

我想创建一个表单来添加经销商到我们的系统,这样他们可以选择哪些品牌相关联(品牌很少,所以我们希望将它们显示为复选框)和什么类型,但试图显示这个到目前为止,品牌形式一直很棘手。

  

品牌实体

/**
 * Brand
 *
 * @ORM\Table()
 * @ORM\Entity
 */

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

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

/**
 * @ORM\ManyToMany(targetEntity="TypeBrand")
 * @ORM\JoinTable(name="brand_type",
 *      joinColumns={@ORM\JoinColumn(name="brand_id", referencedColumnName="id")},
 *      inverseJoinColumns={@ORM\JoinColumn(name="type_id", referencedColumnName="id")}
 *      )
 */
private $type;

/**
 * @ORM\OneToMany(targetEntity="DealerBrand", mappedBy="brand")
*/
private $dealerBrand;

public function __construct()
{
    $this->type = new ArrayCollection();
    $this->dealerBrand = new ArrayCollection();
}

public function __toString()
{
    return $this->getName();
}

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

/**
 * Set name
 *
 * @param string $name
 * @return Brand
 */
public function setName($name)
{
    $this->name = $name;
    $this->setSlug($name);

    return $this;
}

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

public function addType(TypeBrand $type)
{
    $this->type[] = $type;
}

public function getType()
{
    return $this->type;
}

public function addDealerBrand($dealerBrand)
{
    $this->dealerBrand[] = $dealerBrand;
}

public function getDealerBrand()
{
    return $this->dealerBrand;
}

}
  

经销商实体

/**
* Dealer
*
* @ORM\Table("dealer")
* @ORM\Entity(repositoryClass="Project\DealersBundle\Entity\Repository\DealerRepository")
* @Gedmo\Loggable
*/
class Dealer
{
/**
 * @var integer
 *
 * @ORM\Column(name="id", type="integer")
 * @ORM\Id
 * @ORM\GeneratedValue(strategy="AUTO")
 */
private $id;

/**
 * @var string
 *
 * @ORM\Column(name="name", type="string", length=255, unique=true)
 * @Assert\NotBlank()
 * @Assert\Length(min = "10")
 */
private $name;

/**
 * @ORM\OneToMany(targetEntity="DealerBrand", mappedBy="dealer")
 *
*/
private $dealerBrand;

public function __construct()
{
    $this->dealerBrand = new ArrayCollection();
}

public function __toString()
{
    return $this->getName();
}

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

/**
 * Set name
 *
 * @param string $name
 * @return Dealer
 */
public function setName($name)
{
    $this->name = $name;

    return $this;
}

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

public function addDealerBrand($dealerBrand)
{
    $this->dealerBrand[] = $dealerBrand;
}

public function getDealerBrand()
{
    return $this->dealerBrand;
}
}
  

经销商品牌实体

/**
* DealerBrand
*
* @ORM\Table("dealer_brand")
* @ORM\Entity
*/
class DealerBrand
{
/**
 * @var integer
 *
 * @ORM\Id
 * @ORM\ManyToOne(targetEntity="Dealer", inversedBy="dealerBrand")
 */
private $dealer;

/**
 * @var integer
 *
 * @ORM\Id
 * @ORM\ManyToOne(targetEntity="Brand", inversedBy="dealerBrand")
 */
private $brand;

/**
 * Set dealer
 *
 * @param integer $dealer
 * @return DealerBrand
 */
public function setDealer($dealer)
{
    $this->dealer = $dealer;

    return $this;
}

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

/**
 * Set brand
 *
 * @param integer $brand
 * @return DealerBrand
 */
public function setBrand($brand)
{
    $this->brand = $brand;

    return $this;
}

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

现在这是我的formtypes

  

DealerBrandType

class DealerBrandType extends AbstractType
{
public function buildForm(FormBuilderInterface $builder, array $options)
{
    $builder->add('brand', 'entity', array(
                'class'     => 'Project\DealersBundle\Entity\Brand',
                'property'  => 'name',
                'multiple'  => true,
                'expanded'  => true,
            ));
}

public function setDefaultOptions(OptionsResolverInterface $resolver)
{
    $resolver->setDefaults(
        array(
            'data_class' => 'Project\DealersBundle\Entity\DealerBrand'
        )
    );
}

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

}

  

DealerType

    class DealerType extends AbstractType
    {
    public function buildForm(FormBuilderInterface $builder, array $options)
    {
        $builder
            ->add('name')
            ->add('dealerBrand', 'collection', array(
                    'type'          => new DealerBrandType(),
                    'allow_add'     => true,
                    'allow_delete'  => true,
                ))
            ->add('Save', 'submit');
    }

    public function setDefaultOptions(OptionsResolverInterface $resolver)
    {
        $resolver->setDefaults(
            array(
                'data_class' => 'Project\DealersBundle\Entity\Dealer'
            )
        );
    }

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

And this is my controller

public function addAction()
{
        $dealer = new Dealer();

        $form = $this->createForm(new DealerType(), $dealer);

        $form->handleRequest($this->getRequest());

        if ($form->isValid()) {

            $this->getDoctrine()->getManager()->persist($dealer);
            $this->getDoctrine()->getManager()->flush();

            return $this->redirect($this->generateUrl('dealers_list'));
        }

        return $this->render(
            'ProjectDealersBundle:Dealers:AddDealer.html.twig',
            array(
                'form' => $form->createView()
            )
        );
    }

如果这不是正确的方法,请告诉我,如果你看到错误的代码也告诉我,这样我可以改进

*编辑*

这是我需要的结果

http://tinypic.com/r/24pkzdc/8

你可以在那里看到品牌等......所以我们的想法是,在保存经销商时你也可以保存与品牌的联系

* END EDIT *

谢谢!

1 个答案:

答案 0 :(得分:1)

我不确定这是有史以来最好的答案,但您可以通过在表单中​​进行自定义查询来实现:

        ->add('contact', 'entity', array(
            'class'         => 'AcmeBundle:Entity'
            'query_builder' => function ( \acme\bundle\Entity\entityRepository $c){

                $qb = $c->createQueryBuilder('a');

                return  $qb->orderBy('a.nom', 'ASC')
                            ->join('a.categories', 'c')
                            ->where( $qb->expr()->in ( 'c.id', ':listCategories') )
                                ->setParameter( 'listCategories', array (
                                    7, 
                                ));
            },
            'attr'          => array( 'class' => 'other')                
        ))
    ;
}

通过使用'entity'字段类型,我可以使用'query_builder'选项注入自定义查询(有关详细信息:http://symfony.com/doc/current/reference/forms/types/entity.html

然后,我在内部声明了一个匿名函数(http://php.net/manual/en/functions.anonymous.php)来使用createQueryBuilder创建我的自定义查询。

使用createQueryBuilder,您可以创建自定义查询(这里我几乎喜欢您的多对多关系,我想只使用过滤数组(set参数)获取其中一些。

此处是自定义查询的文档:http://symfony.com/doc/current/book/doctrine.html

查询结果(如果不为空)将显示在表单

/ **替代答案** /

如果您想在您的选择中显示您的经销商和品牌树,那么您必须:

1)进行查询以返回您的经销商和品牌的对象容器

2)创建一个深度为array的数组:

这里有一个例子来说明:

    ->add('contact', 'entity', array(
        'class'         => 'AcmeBundle:Entity'
        'query_builder' => function ( \acme\bundle\Entity\entityRepository $c){

            $dealers = $c->yourFunctionThatReturnesDealers('d');

            $dealersGroupedByBrands = array();
    foreach ( $dealers as $dealer) {
                    foreach ($dealers->getBrands() as $brand) {
            $dealersGroupedByBrands[$brand->getName()][] = $dealer;
        }

            return  $dealersGroupedByBrands;
        },
        'attr'          => array( 'class' => 'other')                
    ))
;

    }

很酷,不是吗?