Doctrine 2:Form字段显示Doctrine \ Common \ Collections \ ArrayCollection @ 00作为值

时间:2014-11-28 17:29:40

标签: doctrine-orm zend-framework2 doctrine zend-form2

我是Zend Framework 2和Doctrine 2的新手,所以我甚至不确定如何搜索或调试我的问题。

我有3个数据库表

1。广告
ID
adverttitle ...

2。类
ID
分类名称 ...

第3。 advert_category
advert_id
CATEGORY_ID

我创建了2个实体,广告和类别。我现在有一个表单,我可以在其中显示可供选择的类别。我使用jQuery将类别显示为列表而不是下拉列表,以及可选择的功能。因此,当您单击某个类别时,此侦听器的值将输入到名为categories的隐藏输入字段中。

一切正常,除了当我显示表单时,隐藏的类别输入字段的值为 Doctrine \ Common \ Collections \ ArrayCollection @ 000000000 ..... 而不是空。我在这做错了什么?我试图找到一个解决方案,但没有成功。

我选择了ManyToMany关系,因为我希望最后能够保存超过1个类别。目前它只使用1,但这样我以后就可以改变它。

这是我的广告实体:

namespace Advert\Entity;

use Doctrine\ORM\Mapping as ORM;
use Doctrine\Common\Collections\ArrayCollection;
use DateTime;

/** Advert
 * 
 * @ORM\Table(name="advert")
 * @ORM\Entity(repositoryClass="Advert\Repository\AdvertRepository")
 */

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


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

 /** 
  * @ORM\ManyToMany(targetEntity="Category", inversedBy="adverts", cascade={"persist"}) 
  * @ORM\JoinTable(name="advert2category") 
  */
  private $categories;

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

 /**
  * Set categories
  *
  * @param ArrayCollection $category
  * @return Advert
  */
  public function setCategories($categories)
  {
    $this->categories = $categories;
    return $this;
  }


 /**
  * Get categories
  *
  * @return ArrayCollection
  */
  public function getCategories()
  {
    return $this->categories;
  }

  /**
   * @param Collection $categories
   */
  public function addCategories($categories)
  {
    foreach ($categories as $category) {
        $this->categories->add($category);
    }
  }

  /**
   * @param Collection $categories
   */
  public function removeCategories($categories)
  {
    foreach($categories as $category){
        $this->categories->removeElement($category);
    }

  }

广告实体中是否存在导致此问题的错误?我希望有人能帮帮忙。我几周以来就遇到过这个问题,无法让它正常工作。

更新 - 将我的表格和部分控制器添加到呼叫表单

下面的表单显示2个下拉元素和2个隐藏的输入字段。 2下拉字段通过jQuery变成可选列表。当您从Maincategory单击List元素时,Subcategories将再次显示所选Maincategory作为可选列表。然后将MaincategoryID输入到隐藏的categoryID字段中。一旦从List中选择子类别,该类别的ID就会写入隐藏的类别字段中。点击“下一步”按钮可以将$ _POST ['categories']的值与我的链接表中的advertID一起保存。

use Zend\Form\Form;
use DoctrineModule\Persistence\ObjectManagerAwareInterface;
use Doctrine\Common\Persistence\ObjectManager;

class CategoryForm extends Form implements ObjectManagerAwareInterface
{

protected $objectManager;


public function __construct()
{       
    $this->setInputFilter(new AdvertFilter());
    parent::__construct('category');


}

public function init()
{
    $this->setAttribute('method', 'post');




    $this->add(array(
            'name' => 'categories',
            'attributes' => array(
                    'type' => 'hidden',
                    'id'    => 'categories',

            ),
            'options'=> array(
                    'label'=> 'categories',
                    ),


    ));


    $this->add(
            array(

                    'type' => 'DoctrineModule\Form\Element\ObjectSelect',
                    'name' => 'categoriesList',

                    'options' => array(

                            'object_manager' => $this->getObjectManager(),
                            'label' => 'Main Category',
                            'target_class'   => 'Advert\Entity\Category',
                            'property'       => 'name',
                            'is_method' => true,

                            'find_method'        => array(
                                    'name'   => 'getMainCategories',
                            ),
                    ),
                    'allow_empty'  => true,
                    'required'     => false,
                    'attributes' => array(
                            'id' => 'categoryList',
                            'multiple' => true,


                    )
            )
    );

    $this->add(
            array(
                    'type' => 'DoctrineModule\Form\Element\ObjectSelect',
                    'name' => 'subcategoryList',
                    'options' => array(
                            'object_manager' => $this->getObjectManager(),
                            'label' => 'Sub Category',


                            'target_class'   => 'Advert\Entity\Category',
                            'property'       => 'name',

                            'is_method' => true,
                            'find_method'        => array(
                                    'name'   => 'getSubCategories',
                            ),
                    ),
                    'allow_empty'  => true,
                    'required'     => false,
                    'attributes' => array(

                            'id' => 'subcategoryList',
                            'multiple' => true,
                            )
            )
    );


    $this->add(array(
            'type' => 'hidden',
            'name' => 'categoryID',
            'options'=> array(
                    'label'=> 'categoryID'),
            'attributes' => array(
                    'id' => 'categoryID',
                    'value' => '1',
            )
    ));

   $this->add(array(
            'name' => 'submit',
            'attributes' => array(
                    'type'  => 'submit',
                    'value' => 'Next',
                    'id' => 'submitbutton',
            ),
    ));



}

public function setObjectManager(ObjectManager $objectManager)
{
    $this->objectManager = $objectManager;
}

public function getObjectManager()
{
    return $this->objectManager;
}

}

在我的控制器中,我通过以下方式调用我的表单:

    $sl = $this->getServiceLocator();
    $form = $sl->get('FormElementManager')->get('\Advert\Form\CreateForm');

    # create a new, empty entity
    $advert = new Advert();

    # set the hydrator to connect form and entity
    $form->setHydrator(new DoctrineHydrator($this->getEntityManager(),'Advert\Entity\Advert'));

    # connect form and entity
    $form->bind($advert);

1 个答案:

答案 0 :(得分:0)

首先,双向关系不使用连接表。您的映射似乎是双向的,但是您尝试使用第三个表:advert_category

我建议将$categories实体的Advert属性的映射更改为单向关系:

class Advert
{
     // ...

    /**
     * @ORM\ManyToMany(targetEntity="Category")
     * @ORM\JoinTable(name="advert_category",
     *      joinColumns={@ORM\JoinColumn(name="advert_id", referencedColumnName="id")},
     *      inverseJoinColumns={@ORM\JoinColumn(name="category_id", referencedColumnName="id")}
     *      )
     **/
    protected $categories;

    // ...
}

如果您想利用DoctrineObject hydrator,还应该在addCategories(Collection $categories)实体中实施removeCategories(Collection $categories)Advert方法。 (我假设你正在使用DoctrineORMModule)。

此时,您的Category实体不应该对Advert了解任何内容,并且您无法通过$category->getAdverts()等实体方法直接访问类别实例中的所有广告。但是,在需要时,您可以轻松地在AdvertRepository中编写getAdvertsByCategoryId($categoryId)方法。

最后一个细节是,您应该有一个CategoryFieldset(还需要使用Category实体作为对象),您必须使用{在表单的categories元素中指向此字段集{1}}配置密钥或直接提供实例本身。

例如:

target_element

我强烈建议使用$formManager = $serviceLocator->get('FormElementManager'); $form = $formManager->get('your\form\name'); $form->add( array( 'name' => 'categories', 'type' => 'Zend\Form\Element\Collection', 'options' => array( 'target_element' => $formManager->get('your\fieldset\name'); // or you can do this but probably you will also need $entityManager // inside the CategoryFieldset // 'target_element' => new CategoryFieldset(); ), ) ); 来获取由FormElementManagernew AdvertForm()直接实例化的表单和字段集实例。编写new CategoryFieldset()也是一种很好的做法,可以正确地将AbstractFormElementFactory依赖项注入到字段集和表单中。

希望它有所帮助。