Zend Framework 2 Doctrine 2 多对多实体关系问题

问题描述 投票:0回答:3

我有以下表格:电影、类别、电影_类别和实体:

电影.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);
        }
    }
}

类别.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,                 
            ),                  
        );  
    }

}

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',
            )
        ));
    }


}

添加操作:

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”

请帮帮我,我真的被这个吓坏了!谢谢你:)

php doctrine-orm many-to-many zend-framework2 entity
3个回答
1
投票

据我所知,您的实体正在接收类似的东西Admin\Entity\Film#categories,在这一部分中,类别具有一定的价值。您的实体需要一个类型为 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);
}

然后在你的操作中,你必须将Category的对象传递给Film实体,就像这样

  $Film->SetCategory($categoryObj);

当然你必须根据你的部分设置你的业务逻辑,但是这个错误应该被这个方法删除。


0
投票

您需要为目标实体定义 FQCN。

改变:

* @ORM\ManyToMany(targetEntity="Category")

至:

* @ORM\ManyToMany(targetEntity="Admin\Entity\Category")

0
投票

这与水合作用和延迟加载有关。 我不是这方面的专家,但是 #categories 是一个代理对象,当您要保存它时,它会抱怨,因为它需要是一个实际的集合,而不是集合的代理对象。

如果您采用了 noobie-php 的方法,您将在主对象上重新附加新的类别对象,因此它们不再是代理。

这令人沮丧,因为 Doctrine 本来应该避免很多麻烦,但在很多情况下它实际上并没有达到您自然期望的效果。 我前段时间发现了一个关于此问题的错误票,但现在找不到它 - 如果我能找到它,我会将其添加到此。

© www.soinside.com 2019 - 2024. All rights reserved.