我是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);
答案 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();
),
)
);
来获取由FormElementManager
和new AdvertForm()
直接实例化的表单和字段集实例。编写new CategoryFieldset()
也是一种很好的做法,可以正确地将AbstractFormElementFactory
依赖项注入到字段集和表单中。
希望它有所帮助。