xaaleja
xaaleja

Reputation: 81

Catchable Fatal Error: Argument 1 passed to (...) must be an instance of (...) integer given

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

Answers (2)

Sybio
Sybio

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

Ahmed Siouani
Ahmed Siouani

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

Related Questions