Bidirectional references on Doctrine Fixtures

◇◆丶佛笑我妖孽 提交于 2019-12-08 04:21:44

问题


I have a db with movies and awards. The point is what I want is be able to know the movie of an award and the awards of a movie. The problem begins when I try to load a movie or an award. When I load one of them I have an error that says, for example: undefined award-1 or viceversa (undefined movie-1) because the references aren't created yet.

My Awards Fixture:

namespace MyProject\MovieBundle\DataFixtures\MongoDB;

use Doctrine\Common\DataFixtures\AbstractFixture;
use Doctrine\Common\DataFixtures\OrderedFixtureInterface;
use Doctrine\Common\Persistence\ObjectManager;

use MyProject\MovieBundle\Document\Award;

class Awards extends AbstractFixture implements OrderedFixtureInterface {
    public function load(ObjectManager $manager) {
        $awards = array(
            array(
                "name"     => "Sitges",
                "year"     => "1992",
                "category" => "Best director"
                "movie"    => $this->getReference("movie-1"),
            array(
                "name"     => "Toronto''s festival",
                "year"     => "1992",
                "category" => "FIPRESCI award",
                "movie"    => $this->getReference("movie-1")
        );

        foreach ($awards as $i => $award) {
            $i++;
            $document = new Award();
            $document->setName    ($award["name"]);
            $document->setYear    ($award["year"]);
            $document->setCategory($award["category"]);

            $manager->persist($document);
            $this->addReference("award-" . $i, $document);
        }

        $manager->flush();
    }

    public function getOrder() {
        return 1;
    }
}

And Movies Fixture:

namespace Filmboot\MovieBundle\DataFixtures\MongoDB;

use Doctrine\Common\DataFixtures\AbstractFixture;
use Doctrine\Common\DataFixtures\OrderedFixtureInterface;
use Doctrine\Common\Persistence\ObjectManager;

use Filmboot\MovieBundle\Document\Movie;

class Movies extends AbstractFixture implements OrderedFixtureInterface {
    public function load(ObjectManager $manager) {
        $movies = array(
            array(
                "title"      => "Reservoir Dogs",
                "duration"   => "95",
                "year"       => "1992",
                "country"    => "USA",
                "producer"   => "Live Entertainment, Dog Eat Dog Productions Inc.",
                "image"      => "reservoirdogs.png",
                "largeImage" => "reservoirdogsLarge.png",
                "awards"     => [$this->getReference("award-1"), $this->getReference("award-2")
        );

        foreach ($movies as $i => $movie) {
            $i++;
            $document = new Movie();
            $document->setTitle     ($movie["title"]);
            $document->setDuration  ($movie["duration"]);
            $document->setyear      ($movie["year"]);
            $document->setProducer  ($movie["producer"]);
            $document->setImage     ($movie["image"]);
            $document->setLargeImage($movie["largeImage"]);

            foreach ($movie["awards"] as $award)         {
                $document->addAward($award);
            }
           $manager->persist($document);
           $manager->flush();

           $this->addReference("movie-".$i, $document);
        }
    }

    public function getOrder() {
        return 1;
    }
}   

回答1:


What I tried to explain in a second time here : https://stackoverflow.com/a/19904128/875519 is that you just need first to load Movies, then Awards, and just link movies in Award fixtures, not both. Don't link Awards in movie fixtures, because when loading movie fixtures, awards will not be created, and so the script will crash...

By adding movie to an award object, this is sufficient to create the relation between both object and you'll be able call $movie->getAwards() and $award->getMovie() !

So, class Movies, remove these lines :

"awards"     => [$this->getReference("award-1"), $this->getReference("award-2")

//...

foreach ($movie["awards"] as $award) {
      $document->addAward($award);
}

And set order to 0 (coming before 1, have to be loaded before Awards)

public function getOrder() {
    return 0; // Load before awards
}

class Awards, don't change nothing as you currently create relations with movies, make sure you load Awards after Movies by setting order to 1 :

public function load(ObjectManager $manager) {

    $awards = array(
        array(
            "name"     => "Sitges",
            "year"     => "1992",
            "category" => "Best director"
            "movie"    => $this->getReference("movie-1"), // Link to a movie
        array(
            "name"     => "Toronto''s festival",
            "year"     => "1992",
            "category" => "FIPRESCI award",
            "movie"    => $this->getReference("movie-1") // Link to a movie
    );

    // ...
}

public function getOrder() {
     return 1; // Load after movies
}

Relations between awards and movies will be saved and in the databases field movie_id (of Award class) will be completed !

So, you don't have to add relation in both fixtures. Choose one fixture class that will be loaded after the other one, and add the relation object in this chosen class, not in both, this is sufficient to create the relation between both objects and will solved your problem !



来源:https://stackoverflow.com/questions/19953315/bidirectional-references-on-doctrine-fixtures

易学教程内所有资源均来自网络或用户发布的内容,如有违反法律规定的内容欢迎反馈
该文章没有解决你所遇到的问题?点击提问,说说你的问题,让更多的人一起探讨吧!