0

Symfony2 と Doctrin2のJobエンティティとエンティティの間のカスケード永続化をテストしています。Categoryこれが私のCategoryエンティティです:

<?php
namespace Ibw\JobeetBundle\Entity;

use Doctrine\Common\Collections\ArrayCollection;
use Ibw\JobeetBundle\Entity\Affiliate;
use Ibw\JobeetBundle\Entity\Job;
use Ibw\JobeetBundle\Utils\Jobeet;

use Doctrine\ORM\Mapping as ORM;

/**
 * @ORM\Entity(repositoryClass="Ibw\JobeetBundle\Repository\CategoryRepository")
 * @ORM\Table(name="categories")
 * @ORM\HasLifecycleCallbacks
 */
class Category 
{

    /**
     * @ORM\Id
     * @ORM\Column(type="integer")
     * @ORM\GeneratedValue(strategy="AUTO")
     */
    protected $id;

    /**
     * @ORM\Column(type="string", length=255, unique=true)
     */
    protected $name;

    /**
     * @ORM\OneToMany(targetEntity="Job", mappedBy="category", cascade={"persist"})
     */
    protected $jobs;

    /**
     * @ORM\ManyToMany(targetEntity="Affiliate", mappedBy="categories")
     */
    protected $affiliates;

    /**
     * @ORM\Column(type="string", length=255, unique=true)
     */
    protected $slug;

    /**
     * Constructor
     */
    public function __construct()
    {
        $this->jobs = new ArrayCollection();
        $this->affiliates = new ArrayCollection();
    }

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

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

        return $this;
    }

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

    /**
     * Add jobs
     *
     * @param Job $jobs
     * @return Category
     */
    public function addJob(Job $jobs)
    {
        $this->jobs[] = $jobs;

        return $this;
    }

    /**
     * Remove jobs
     *
     * @param Job $jobs
     */
    public function removeJob(Job $jobs)
    {
        $this->jobs->removeElement($jobs);
    }

    /**
     * Get jobs
     *
     * @return \Doctrine\Common\Collections\Collection 
     */
    public function getJobs()
    {
        return $this->jobs;
    }

    /**
     * Add affiliates
     *
     * @param Affiliate $affiliates
     * @return Category
     */
    public function addAffiliate(Affiliate $affiliates)
    {
        $this->affiliates[] = $affiliates;

        return $this;
    }

    /**
     * Remove affiliates
     *
     * @param Affiliate $affiliates
     */
    public function removeAffiliate(Affiliate $affiliates)
    {
        $this->affiliates->removeElement($affiliates);
    }

    /**
     * Get affiliates
     *
     * @return \Doctrine\Common\Collections\Collection 
     */
    public function getAffiliates()
    {
        return $this->affiliates;
    }

    /**
     * Set slug
     *
     * @param string $slug
     * @return Category
     */
    public function setSlug($slug)
    {
        $this->slug = $slug;

        return $this;
    }

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

    /**
     * @ORM\PrePersist
     * @ORM\PreUpdate
     */
    public function setSlugValue()
    {
        $this->setSlug(Jobeet::slugify($this->getName()));
    }
}

その中のカスケード持続部分は次のとおりです。

/**
 * @ORM\OneToMany(targetEntity="Job", mappedBy="category", cascade={"persist"})
 */
protected $jobs;

今、このテストを使用してテストしようとすると:

public function testAddJobToCategory()
    {
        $job = new Job();
         $job->setType('flexible-time');
         $job->setCompany('Sensio Labs');
         $job->setLogo('sensio-labs.gif');
         $job->setUrl('http://www.sensiolabs.com/');
         $job->setPosition('Web Developer');
         $job->setLocation('Paris, France');
         $job->setDescription('You\'ve already developed websites with symfony and you want to work with Open-Source technologies. You have a minimum of 3 years experience in web development with PHP or Java and you wish to participate to development of Web 2.0 sites using the best frameworks available.');
         $job->setHowToApply('Send your resume to fabien.potencier [at] sensio.com');
         $job->setIsPublic(true);
         $job->setIsActivated(true);
         $job->setToken('job');
         $job->setEmail('job@example.com');
         $job->setExpiresAt(new \DateTime('+30 days'));

         $category = $this->em->createQueryBuilder('c')
                        ->select('c')
                        ->from('IbwJobeetBundle:Category', 'c')
                        ->where('c.id = 1')
                        ->getQuery()
                        ->getSingleResult();

        $category->addJob($job);
        $this->em->persist($category);
        $this->em->flush();

        $jobFromQuery = $this->em->createQueryBuilder('j')
                    ->select('j')
                    ->from('IbwJobeetBundle:Job', 'j')
                    ->where('j.type = :type')
                    ->setParameter('type', 'flexible-time')
                    ->setMaxResults(1)
                    ->setFirstResult(1)
                    ->getQuery()
                    ->getSingleResult();


        $this->assertEquals(1, $jobFromQuery->getCategory()->getId());
    }

このテストを実行すると、次のエラーが発生します。

PHP 致命的なエラー: 非オブジェクトでのメンバー関数 getId() の呼び出し

だからその$jobFromQuery->getCategory()->getId()部分だと思います。getCategory()設定されていないか何か。

4

1 に答える 1

0

このドクトリン文書http://docs.doctrine-project.org/en/latest/reference/unitofwork-associations.htmlは言う:

Doctrine は関連付けの所有側の変更のみをチェックします。

これを完全に理解するには、オブジェクトの世界で双方向の関連付けがどのように維持されるかを思い出してください。関連付けの両側に 2 つの参照があり、これら 2 つの参照は両方とも同じ関連付けを表しますが、互いに独立して変更できます。もちろん、正しいアプリケーションでは、双方向関連のセマンティクスはアプリケーション開発者によって適切に維持されます (それは開発者の責任です)。Doctrine は、これら 2 つのメモリ内参照のどちらが永続化されるべきもので、どれが永続化されるべきでないのかを知る必要があります。これは、所有/逆の概念が主に使用されるものです。

関連の逆側のみに加えられた変更は無視されます。双方向の関連付けの両側 (または、Doctrine の観点からは、少なくとも所有側) を更新してください。

双方向アソシエーションの所有側は、アソシエーションの状態を判断する際に Doctrine が「見る」側であり、その結果、データベース内のアソシエーションを更新するために何かする必要があるかどうかを判断します。

あなたのコード$category->addJob($job);では、逆側で関連付けを設定しているだけです。無視されているドキュメントと同様に、少なくとも$job->setCategory($category)最初に行う必要があります。

于 2013-10-05T23:12:35.353 に答える