我有以下表格:电影,类别,电影_类别和实体:
Film.php
<?php
namespace Admin\Entity;
use Doctrine\Common\Collections\ArrayCollection;
use Doctrine\Common\Collections\Collection;
use Doctrine\ORM\Mapping as ORM;
/**
* @ORM\Table(name="films")
*/
class Film{
/**
* @ORM\Id
* @ORM\GeneratedValue(strategy="AUTO")
* @ORM\Column(type="integer")
* @ORM\Column(length=11)
*/
private $id;
/**
* @ORM\Column(type="string")
*/
private $name;
/* .... */
/**
* @ORM\ManyToMany(targetEntity="Category")
* @ORM\JoinTable(name="films_categories",
* joinColumns={@ORM\JoinColumn(name="film_id", referencedColumnName = "id")},
* inverseJoinColumns={@ORM\JoinColumn(name="category_id", referencedColumnName="id")})
*/
private $categories;
public function __construct(){
$this->categories = new ArrayCollection();
}
public function getCategoriesNames(){
$names = array();
foreach($this->categories as $category){
$names[] = $category->getName();
}
return $names;
}
public function getId(){
return $this->id;
}
public function setId($id){
$this->id = $id;
}
/* ... */
/**
* @return Collection
*/
public function getCategories(){
return $this->categories;
}
public function addCategories(Collection $categories){
foreach($categories as $category){
$this->categories->add($category);
}
}
public function removeCategories(Collection $categories){
foreach($categories as $category){
$this->categories->removeElement($category);
}
}
}
Category.php
<?php
namespace Admin\Entity;
use Doctrine\ORM\Mapping as ORM;
/**
* @ORM\Table(name="categories")
*/
class Category {
/**
* @ORM\Id
* @ORM\GeneratedValue(strategy="AUTO")
* @ORM\Column(type="integer")
*/
private $id;
/* ... */
public function getId(){
return $this->id;
}
public function setId($id){
$this->id = $id;
}
/* ... */
}
我想要做的是创建一个表单以及添加新电影并为其分配类别的操作。这是我使用的表格:
FilmFieldset.php
<?php
namespace Admin\Form;
use Zend\Form\Fieldset;
use Zend\InputFilter\InputFilterProviderInterface;
use DoctrineORMModule\Stdlib\Hydrator\DoctrineEntity;
use Admin\Entity\Film;
class FilmFieldset extends Fieldset implements InputFilterProviderInterface{
protected $entityManager;
public function __construct($em){
parent::__construct('film');
$this->entityManager= $em;
$this->setHydrator(new DoctrineEntity($em,'Admin\Entity\Film'))
->setObject(new Film());
#$this->setAttribute('method','post');
#$this->setAttribute('class','standardForm');
$this->add(array(
'name' => 'id',
'type' => 'hidden'
));
/* ... */
$this->add(
array(
'type' => 'DoctrineModule\Form\Element\ObjectSelect',
'name' => 'categories',
'attributes' => array(
'multiple' => 'multiple',
),
'options' => array(
'object_manager' => $em,
'target_class' => 'Admin\Entity\Category',
'property' => 'name',
'label' => 'Categories: ',
'disable_inarray_validator' => true
),
)
);
}
public function getInputFilterSpecification(){
return array(
/* .... */
'categories' => array(
'required' => true,
),
);
}
}
The FilmForm.php
<?php
namespace Admin\Form;
use Zend\Form\Form;
use Zend\Stdlib\Hydrator\ClassMethods;
use Admin\Entity\Film;
use Zend\InputFilter\InputFilter;
use DoctrineModule\Stdlib\Hydrator\DoctrineObject as DoctrineHydrator;
class FilmForm extends Form{
public function __construct($em){
parent::__construct('filmForm');
$this->setAttribute('method','post')
->setAttribute('class','standardForm')
->setHydrator(new DoctrineHydrator($em,'\Admin\Entity\Film'))
->setInputFilter(new InputFilter());
/* I register the fieldset through a service and not directly here */
// $this->add(array(
// 'type' => new FilmFieldset($em),
// 'options' => array(
// 'user_as_base_fieldset' => true
// )
// ));
$this->add(array(
'name' => 'security',
'type' => 'Zend\Form\Element\Csrf'
));
$this->add(array(
'name' => 'submit',
'type' => 'submit',
));
$this->setValidationGroup(array(
'security',
'film' => array(
'categories',
)
));
}
}
addAction:
public function addAction() {
$em = $this->getEntityManager();
$form = $this->getForm();
$film = new Film();
$form->bind($film);
if($request->isPost()){
$post = array_merge_recursive(
$request->getPost()->toArray(),
$request->getFiles()->toArray()
);
$form->setData($post);
if($form->isValid()){
$categories = array();
foreach($post['film']['categories'] as $categoryId){
$categories[] = $em->getRepository('Admin\Entity\Category')->find($categoryId);
}
$film->addCategories($categories);
$em->persist($film);
$em->flush();
}else{
// the form is not valid
}
}
结果是各种错误和ORMExcption,消息“找到关联Admin \ Entity \ Film#categories上的类型实体,但期望Admin \ Entity \ Category”
请帮帮我,我真的很害怕!谢谢:))
答案 0 :(得分:1)
从我发现的是这样的事情,你的实体正在接收管理员\实体\电影#类别,在这部分类别是一些价值。您的实体期望 Admin \ Entity \ Film#categories 类型的对象。
要克服这一点,你必须创建一个
public function SetCategory(Admin\Entity\Category Category)
{
$this->categories(or category or w/e your variable name is)= Category;
}
public function getCategory()
{
return $this->categories(or category or w/e your variable name is);
}
然后在你的行动中你必须将类别的对象传递给电影实体这样的事情
$Film->SetCategory($categoryObj);
当然,您必须根据您的部分设置业务逻辑,但此错误应由此apporach删除。
答案 1 :(得分:0)
您需要为targetEntity定义FQCN。
变化:
* @ORM\ManyToMany(targetEntity="Category")
为:
* @ORM\ManyToMany(targetEntity="Admin\Entity\Category")
答案 2 :(得分:0)
这与水合和懒惰负荷有关。我不是这方面的专家,但#categories是一个代理对象,当你要保存它时,它会抱怨,因为它需要是一个真正的集合,而不是集合的代理对象。
如果您使用了noobie-php的方法,那么您将在主要对象上重新附加新的类别对象,因此它们不再是代理。
这令人沮丧,因为Doctrine本来应该省去很多麻烦,但实际上并没有做到你在许多情况下自然期望的事情。我前段时间发现了一张错误票,但现在找不到它 - 如果我能找到它就会加入它。