0

I recently asked the following question:

Many to Many, One to Many or Many to One

After doing the updates suggested by @inanzzz my database looks great now however my fixtures seem to not work. I get the following error when trying to load them:

[Symfony\Component\Debug\Exception\ContextErrorException]
Catchable Fatal Error: Argument 1 passed to BBQ\Charcoal\WebsiteBundle\Enti
ty\Templates::addModule() must be an instance of BBQ\Charcoal\WebsiteBundle
\Entity\TemplateModules, instance of Proxies\__CG__\BBQ\Charcoal\WebsiteBun
dle\Entity\Modules given, called in /Users/alexward/dev/symphony/symphony20
14/www/src/BBQ/Charcoal/WebsiteBundle/DataFixtures/ORM/TemplateFixtures.php
 on line 19 and defined in /Users/alexward/dev/symphony/symphony2014/www/sr
c/BBQ/Charcoal/WebsiteBundle/Entity/Templates.php line 141

Line 141 of templates.php is:

/**
 * Add modules
 *
 * @param \BBQ\Charcoal\WebsiteBundle\Entity\TemplateModules $modules
 * @return Templates
 */
public function addModule(\BBQ\Charcoal\WebsiteBundle\Entity\TemplateModules $modules)
{
    $this->modules[] = $modules;

    return $this;
}

Here are my entity classes:

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

/**
 * @ORM\Column(type="string", length=10)
 */
protected $type;

 /**
 * @ORM\Column(type="string")
 */
protected $name;

 /**
 * @ORM\Column(type="string")
 */
protected $friendly_name;

/**
 * @ORM\Column(type="text")
 */
protected $description;

/**
 * @ORM\Column(type="integer")
 */
protected $max_limit;

/**
 * @ORM\Column(type="integer")
 */
protected $min_limit;

/**
 * @var ArrayCollection
 * @ORM\OneToMany(targetEntity="TemplateModules", mappedBy="modules")
 */
private $templates;

/**
 * @var ArrayCollection
 * @ORM\OneToMany(targetEntity="Content", mappedBy="modules")
 */
private $content;

public function __construct() {
    $this->templates = new \Doctrine\Common\Collections\ArrayCollection();
    $this->content = new \Doctrine\Common\Collections\ArrayCollection();
}
}


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

 /**
 * @ORM\ManyToOne(targetEntity="Templates", inversedBy="modules")
 */
protected $templates;

/**
 * @ORM\ManyToOne(targetEntity="Modules", inversedBy="templates")
 */
protected $modules;

/**
 * @ORM\Column(type="integer")
 */
private $order_by;
}

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

 /**
 * @ORM\Column(type="string")
 */
protected $name;

 /**
 * @ORM\Column(type="string")
 */
protected $friendly_name;

/**
 * @var ArrayCollection
 * @ORM\OneToMany(targetEntity="Pages", mappedBy="template")
 */
private $pages;

/**
 * @ORM\OneToMany(targetEntity="TemplateModules", mappedBy="templates")
 **/
protected $modules;

public function __construct() {
    $this->pages = new \Doctrine\Common\Collections\ArrayCollection();
    $this->modules = new \Doctrine\Common\Collections\ArrayCollection();
}
}

Here are my fixtures for the two sections:

Modules:

<?php

namespace BBQ\Charcoal\WebsiteBundle\DataFixtures\ORM;

use Doctrine\Common\DataFixtures\AbstractFixture;
use Doctrine\Common\DataFixtures\OrderedFixtureInterface;
use Doctrine\Common\Persistence\ObjectManager;
use BBQ\Charcoal\WebsiteBundle\Entity\TemplateModules;
use BBQ\Charcoal\WebsiteBundle\Entity\Modules;

class ModulesFixtures extends AbstractFixture implements OrderedFixtureInterface
{
public function load(ObjectManager $manager)
{
    $module1 = new Modules();
    $module1->setName('info_box_three_up');
    $module1->setFriendlyName('Information Module (3 to a row)');
    $module1->setDescription('Information Module (3 to a row)');
    $module1->setMinLimit(1);
    $module1->setMaxLimit(1);
    $module1->setType('row');
    $manager->persist($module1);

    $module2 = new Modules();
    $module2->setName('cta_single_line_text');
    $module2->setFriendlyName('Single line CTA with button');
    $module2->setDescription('Single line CTA with button');
    $module2->setMinLimit(1);
    $module2->setMaxLimit(1);
    $module2->setType('row');
    $manager->persist($module2);

    $module3 = new Modules();
    $module3->setName('video');
    $module3->setFriendlyName('Video panel');
    $module3->setDescription('Video panel');
    $module3->setMinLimit(2);
    $module3->setMaxLimit(2);
    $module3->setType('row');
    $manager->persist($module3);

    $module4 = new Modules();
    $module4->setName('stories_two_up');
    $module4->setFriendlyName('Stories (2)');
    $module4->setDescription('Stories (2)');
    $module4->setMinLimit(2);
    $module4->setMaxLimit(2);
    $module4->setType('row');
    $manager->persist($module4);

    $module5 = new Modules();
    $module5->setName('cta_multi_line_text');
    $module5->setFriendlyName('Multiple line CTA with button');
    $module5->setDescription('Multiple line CTA with button');
    $module5->setMinLimit(1);
    $module5->setMaxLimit(1);
    $module5->setType('row');
    $manager->persist($module5);

    $manager->flush();

    $this->addReference('module-1', $module1);
    $this->addReference('module-2', $module2);
    $this->addReference('module-3', $module3);
    $this->addReference('module-4', $module4);
    $this->addReference('module-5', $module5);
}

public function getOrder()
{
    return 1;
}

}

Templates:

<?php

namespace BBQ\Charcoal\WebsiteBundle\DataFixtures\ORM;

use Doctrine\Common\DataFixtures\AbstractFixture;
use Doctrine\Common\DataFixtures\OrderedFixtureInterface;
use Doctrine\Common\Persistence\ObjectManager;
use BBQ\Charcoal\WebsiteBundle\Entity\Templates;
use BBQ\Charcoal\WebsiteBundle\Entity\Modules;
use BBQ\Charcoal\WebsiteBundle\Entity\TemplateModules;

class TemplatesFixtures extends AbstractFixture implements OrderedFixtureInterface
{
public function load(ObjectManager $manager)
{
    $template1 = new Templates();
    $template1->setName('T1_Homepage');
    $template1->setFriendlyName('Homepage Template');
    $template1->addModule($this->getReference('module-1'));
    $template1->addModule($this->getReference('module-2'));
    $template1->addModule($this->getReference('module-3'));
    $template1->addModule($this->getReference('module-4'));
    $template1->addModule($this->getReference('module-5'));

    $manager->persist($template1);

    $manager->flush();

    $this->addReference('template-1', $template1);
}

public function getOrder()
{
    return 2;
}
}
Community
  • 1
  • 1
Alex Foxleigh
  • 1,784
  • 2
  • 21
  • 47

1 Answers1

1

This is how it should be because your table/method/entity is expecting a specific object rather than something else like integer, another object so on.

->addModule(instanbe of TemplateModules is expected here)
but you have given
->addModule(instance of Modules is expected here)

If you say it should definitely be $this->modules[] = $modules; then you probably have set relationships wrong or something similar. You might need to check the relationships.

EDIT:

Look at the difference between you code and mine. You don't have JoinColumn bit in your annotations. I used Student and Course as an example.

class Student
class Modules
{
    /**
     * @ORM\OneToMany(targetEntity="TemplateModules", mappedBy="modules")
     * 
     * @ORM\OneToMany(targetEntity="StudentCourse", mappedBy="studentMap")
     */
    private $templates;
    protected $studentInverse;

    public function __construct() {
        $this->templates = new \Doctrine\Common\Collections\ArrayCollection();
        $this->studentInverse = new \Doctrine\Common\Collections\ArrayCollection();

    }
}

class StudentCourse
class TemplateModules
{
    /**
     * @ORM\ManyToOne(targetEntity="Modules", inversedBy="templates")
     * 
     * @ORM\ManyToOne(targetEntity="Student", inversedBy="studentInverse")
     * @ORM\JoinColumn(name="student", referencedColumnName="id")
     */
    protected $modules;
    protected $studentMap;

     /**
     * @ORM\ManyToOne(targetEntity="Templates", inversedBy="modules")
     * 
     * @ORM\ManyToOne(targetEntity="Course", inversedBy="courseInverse")
     * @ORM\JoinColumn(name="course", referencedColumnName="id")
     */
    protected $templates;
    protected $courseMap;
}


class Course
class Templates
{
    /**
     * @ORM\OneToMany(targetEntity="TemplateModules", mappedBy="templates")
     * 
     * @ORM\OneToMany(targetEntity="StudentCourse", mappedBy="courseMap")
     **/
    protected $modules;
    protected $courseInverse;

    public function __construct() {
        $this->modules = new \Doctrine\Common\Collections\ArrayCollection();
        $this->courseInverse = new \Doctrine\Common\Collections\ArrayCollection();
    }
}

EDIT 2:

Sound like this is what is happening in your case:

$studentId = 1;
$courseId = 1;

$studentCourse = new StudentCourse();
$studentCourse->setStudentMap($studentId);
$studentCourse->setCourseMap($courseId);

$em = $this->getDoctrine()->getManager();
$em->persist($studentCourse);
$em->flush();

Above will not work! Below is how it should be because your middle table is expecting an object rather than something else like integer so on.

->addModule(instance of TemplateModules is expected here)
but you have given
->addModule(instance of Modules)

EDIT 3:

Your fixtures looks a bit complex to me. Simplified Example Fixtures. Do things one by one (little bit) so that you can easily debug.

$em = $this->getDoctrine()->getManager();

$modules = new Modules();
$modules->.....
$em->persist($modules);


$templates = new Templates();
$templates->.....
$em->persist($templates);


$templateModules = new TemplateModules();
$templateModules->setModules($modules);
$templateModules->setTemplates($templates);
$em->persist($templateModules);

$em->flush();
BentCoder
  • 12,257
  • 22
  • 93
  • 165
  • I'm a bit confused. I added the variables and then ran doctrine:generate:entities to create the rest. So did the generator create them wrong? If so what should I do to fix it? – Alex Foxleigh Oct 26 '14 at 16:31
  • Ah ok. It's very possible, I've not quite got the hang of database relationships yet I don't think. If you don't mind, I'll post my entities file in the question so you can take a look. – Alex Foxleigh Oct 26 '14 at 16:32
  • `doctrine:generate:entities` would not do things wrong. – BentCoder Oct 26 '14 at 16:32
  • Yeah that's what I figured. I must have set the relationships up incorrectly then. – Alex Foxleigh Oct 26 '14 at 16:35
  • Check EDIT section please. – BentCoder Oct 26 '14 at 16:50
  • I did have the join column line in but the cookbook suggested it was optional so I tried removing it. Either with or without, it doesn't seem to change the error. – Alex Foxleigh Oct 26 '14 at 16:55
  • Apologies if I'm being a pain. I used to just do this with arrays and not think about DB relationships so this is really new stuff to me. – Alex Foxleigh Oct 26 '14 at 16:56
  • No problem at all. Doctrine can be little complex in very first stage of learning. Make sure you're passing. Also read second EDIT note please. Somewhere in your fixtures, you're doing something wrong. – BentCoder Oct 26 '14 at 17:01
  • That is possible. The fixtures are quite confusing to me now I have that third table. I've added them to an edit on my question. – Alex Foxleigh Oct 26 '14 at 17:07
  • I added EDIT 3 but I think you need to do thinks little by little and simplify your fixtures a bit. – BentCoder Oct 26 '14 at 17:17
  • So basically do them all in one class rather than spread them out? To be honest, the way the symbol tutorial suggests writing fixtures seems really verbose to me anyway. It didn't look like the best method. – Alex Foxleigh Oct 26 '14 at 17:28
  • Doctrine and Symfony documentations are two things that I'm forcing myself to like! First keep things short and simple in one file then separate them if you wish/can. With this way, it will be easier to debug. – BentCoder Oct 26 '14 at 17:38
  • Wow that actually worked! I was basically still not thinking of TemplateModules as an entity, assuming the modules and templates fixtures would take care of things. You were right, putting them in one class really cleared that up! Thank you so much! – Alex Foxleigh Oct 26 '14 at 18:05
  • At the beginning [KISS principle](http://en.wikipedia.org/wiki/KISS_principle) always works. Don't forget to up-vote ;) – BentCoder Oct 26 '14 at 18:07