Reputation: 81
I'm making fixtures and when I try to load them I have an error. I need an instance of a Movie object but what I give, and I don't know why, is an integer. For this reason it says me that I have the following error:
[Symfony\Component\Debug\Exception\ContextErrorException]
Catchable Fatal Error: Argument 1 passed to Filmboot\MovieBundle\Document\A
ward::setMovie() must be an instance of Filmboot\MovieBundle\Document\Movie
, integer given, called in C:\Programming\xampp\htdocs\filmboot.web\src\Fil
mboot\MovieBundle\DataFixtures\MongoDB\Awards.php on line 143 and defined i
n C:\Programming\xampp\htdocs\filmboot.web\src\Filmboot\MovieBundle\Documen
t\Award.php line 107
This is my Fixture class:
namespace Filmboot\MovieBundle\DataFixtures\MongoDB;
use Doctrine\Common\DataFixtures\AbstractFixture;
use Doctrine\Common\DataFixtures\OrderedFixtureInterface;
use Doctrine\Common\Persistence\ObjectManager;
use Filmboot\MovieBundle\Document\Award;
class Awards extends AbstractFixture implements OrderedFixtureInterface {
public function load(ObjectManager $manager) {
$awards = array(
array(
"name" => "Sitges",
"year" => "1992",
"category" => "Best director"
);
foreach ($awards as $award) {
$document = new Award();
$document->setName ($award["name"]);
$document->setYear ($award["year"]);
$document->setCategory($award["category"]);
$manager->persist($document);
$this->addReference("award-" .$i, $award);
}
$manager->flush();
}
public function getOrder() {
return 1;
}
}
And this is the document class:
namespace Filmboot\MovieBundle\Document;
use Doctrine\ODM\MongoDB\Mapping\Annotations as ODM;
use Doctrine\Common\Collections\ArrayCollection;
use Filmboot\MovieBundle\Util;
/**
* @ODM\Document(db="filmbootdb", collection="awards")
* @ODM\Document(repositoryClass="Filmboot\MovieBundle\Document\AwardRepository")
*/
class Award {
/**
* @ODM\Id
*/
private $id;
/**
* @ODM\String
*/
private $name;
/**
* @ODM\Int
*/
private $year;
/**
* @ODM\String
*/
private $category;
/**
* @ODM\ReferenceOne(targetDocument="Movie", mappedBy="awards", cascade={"persist"})
*/
private $movie;
public function getId() {
return $this->id;
}
public function setName($name) {
return $this->name = $name;
}
public function getName() {
return $this->name;
}
public function setYear($year) {
return $this->year = $year;
}
public function getYear() {
return $this->year;
}
public function setCategory($category) {
return $this->category = $category;
}
public function getCategory() {
return $this->category;
}
public function setMovie(\Filmboot\MovieBundle\Document\Movie $movie) {
$movie->setAward($this);
return $this->movie = $movie;
}
}
Upvotes: 3
Views: 14996
Reputation: 8645
As we can see you explicitly give an integer for the movie :
$awards = array(
array(
// ...
"movie" => 1,
),
);
// ...
$document->setMovie ($award["movie"]);
Instead of a movie object, so the script crashes because it requires a Movie object :
public function setMovie(\Filmboot\MovieBundle\Document\Movie $movie) {
return $this->movie = $movie;
}
So the solution is to create the fixtures of the movies and give them a reference:
// When saving inside Movie fixtures
$manager->persist($movie);
$manager->flush();
$this->addReference('movie-'.$i, $movie); // Give the references as movie-1, movie-2...
Then load them first with getOrder() method :
public function getOrder()
{
return 0; // 0, loaded first
}
Control that Awards are loaded after movies :
public function getOrder()
{
return 1; // loaded after 0...
}
and after in your Award fixtures retrieve them like that by reference, it will load the entire object, not just an id (integer) :
$awards = array(
array(
// ...
"movie" => $this->getReference('movie-1'), // Get the Movie object, not just id
),
);
// ...
$document->setMovie ($award["movie"]);
Please note that if you want to use reference and order, your fixture classes need to implement OrderedFixtureInterface :
namespace Acme\HelloBundle\DataFixtures\ORM;
use Doctrine\Common\DataFixtures\AbstractFixture;
use Doctrine\Common\DataFixtures\OrderedFixtureInterface;
use Doctrine\Common\Persistence\ObjectManager;
use Acme\HelloBundle\Entity\Group;
class LoadGroupData extends AbstractFixture implements OrderedFixtureInterface
You have to do this with all your other entities like actors, directors...
You can find the documentation for sharing objects (by reference) between your fixtures here.
EDIT :
to make bidirectionnal working, adapt Award setter :
public function setMovie(\Filmboot\MovieBundle\Document\Movie $movie) {
$movie->setAward($this);
return $this->movie = $movie;
}
and adapt persistance with cascade persist :
/**
* @ODM\ReferenceOne(targetDocument="Movie", mappedBy="awards", cascade={"persist"})
*/
private $movie;
Upvotes: 2
Reputation: 13891
As the error message you got is clear enough. Here's the way you may fix this bad arguments mapping issue.
Instead of setting an integer as a movie
to the awards
array you're using to populate the document
instance. Why don't you just set a given Movie
entity you already persisted.
To do that, you'll have to load one or many movies
(it depends on your needs) and set this/those entit(y/ies) as argument(s) to populate your document
instances.
An example, Take a look at this example (on the question) of user(s) populated by already persisted userGroup(s). You might use here the same idea.
Upvotes: 1