How to use Datafixtureloader

Asked

Viewed 44 times

0

I’m basing myself on this tutorial, but I have the Country and State classes. I’m trying to import the data using the command:

php console doctrine:fixtures:load

when I execute him works for the Countryloader, loads the data and stores it in the database, but fails when trying to load Stateloader.

The message it displays is:

[Symfony\Component\Debug\Exception\ContextErrorException]
Notice: Undefined index: country

How to make the Stateloader work?

Countryloader.php

namespace Test\Bundle\TestBundle\DataFixtures\ORM;

use Hautelook\AliceBundle\Alice\DataFixtureLoader;

/**
 * Description of CountryLoader
 *
 */
class CountryLoader extends DataFixtureLoader {

    protected function getFixtures() {
        return array(
            __DIR__ . '/country.yml',
        );
    }

}

Stateloader.php

namespace Test\Bundle\TestBundle\DataFixtures\ORM;

use Hautelook\AliceBundle\Alice\DataFixtureLoader;

/**
 * Description of StateLoader
 *
 */
class StateLoader extends DataFixtureLoader {

    protected function getFixtures() {
        return array(
            __DIR__ . '/country.yml',
            __DIR__ . '/state.yml',
        );
    }

}

Country.php

/**
 * Description of Country
 * @ORM\Entity
 * @ORM\Table(name="country")
 */
class Country {

    /**
     * @ORM\Id
     * @ORM\Column(type="integer")
     * @ORM\GeneratedValue(strategy="IDENTITY")
     */
    private $id;
    /**
     * @ORM\Column(type="string", length=64, unique=true) 
    */
        private $name;
    /**
     * @ORM\Column(type="string", length=8, unique=true) 
     */
    private $iso3;

    /**
     * @ORM\Column(type="string", length=8, unique=true) 
     */
    private $numcode;

    /**
     * @ORM\Column(type="string", length=8, unique=true) 
     */
    private $acronym;

    /**
     * @ORM\OneToMany(targetEntity="City", cascade={"all"}, mappedBy="country")
     * @var ArrayCollection
     */
    private $states;

    public function getId() {
        return $this->id;
    }
    public function getName() {
        return $this->name;
    }

    public function getIso3() {
        return $this->iso3;
    }

    public function getNumcode() {
        return $this->numcode;
    }

    public function getAcronym() {
        return $this->acronym;
    }

    public function getStates() {
        return $this->states;
    }

    public function setId($id) {
        $this->id = $id;
        return $this;
    }
    public function setName($name) {
        $this->name = $name;
        return $this;
    }
    public function setIso3($iso3) {
        $this->iso3 = $iso3;
        return $this;
    }

    public function setNumcode($numcode) {
        $this->numcode = $numcode;
        return $this;
    }

    public function setAcronym($acronym) {
        $this->acronym = $acronym;
        return $this;
    }

    public function setStates(ArrayCollection $states) {
        $this->states = $states;
        return $this;
    }

}

State.php

/**
 * Description of State
 * @ORM\Entity
 * @ORM\Table(name="state")
 */
class State {

    /**
     * @ORM\Id
     * @ORM\Column(type="integer")
     * @ORM\GeneratedValue(strategy="IDENTITY")
     */
    private $id;
    /**
     * @ORM\Column(type="string", length=64, unique=true) 
     */
    private $name;

    /**
     * @ORM\Column(type="string", length=8, unique=true) 
     */
    private $acronym;

    /**
     * @ORM\OneToMany(targetEntity="City", cascade={"all"}, mappedBy="state")
     * @var ArrayCollection 
     */
    private $cities;

    /**
     * @ORM\ManyToOne(targetEntity="Country", inversedBy="states", cascade={"persist", "remove"})
     * @ORM\JoinColumn(name="country_acronym", referencedColumnName="acronym", onDelete="CASCADE")
     * @var Country
     */
    private $country;

    public function getId() {
        return $this->id;
    }
    public function getName() {
        return $this->name;
    }

    public function getAcronym() {
        return $this->acronym;
    }

    public function getCities() {
        return $this->cities;
    }

    public function getCountry() {
        return $this->country;
    }

    public function setId($id) {
        $this->id = $id;
        return $this;
    }

    public function setName($name) {
        $this->name = $name;
        return $this;
    }
    public function setAcronym($acronym) {
        $this->acronym = $acronym;
        return $this;
    }

    public function setCities(ArrayCollection $cities) {
        $this->cities = $cities;
        return $this;
    }

    public function setCountry(Country $country) {
        $this->country = $country;
        return $this;
    }

}

country yml.

Test\Bundle\TestBundle\Entity\Country:
    BR: 
        iso3: BRA
        acronym: BR
        numcode: 76
        name: Brasil

state yml.

Test\Bundle\TestBundle\Entity\State:
    AC:
        acronym: AC
        name: Acre
        country: @BR    
  • 1

    I was able to make it work properly, with his own example. There were only a few problems in the mapping of entities (which I checked with the command doctrine:schema:validate) and, in addition, I removed the country.yml state loading (otherwise it would load the data in duplicate).

  • I had not using Doctrine:schema:validate, there were several errors in my entities. It is now showing only: [Mapping] FAIL - The Entity-class 'Sbcorp2b Bundle Systembundle Entity State' Mapping is invalid: * The referenced column name 'acronym' has to be a Primary key column on the target Entity class 'Sbcorp2b Bundle Systembundle Entity Country'. [Mapping] FAIL - The Entity-class 'Sbcorp2b Bundle Systembundle Entity City' Mapping is invalid: * The referenced column name 'acronym' has to be a Primary key column on the target Entity class 'Sbcorp2b Bundle Systembundle Entity State'.

  • @Rodrigorigotti removed the @ORM Joincolumn annotations, after checking the errors with Doctrine:schema:validate and fix, saved, but in this case I lost the deletion in Cascade, I no longer have error in Doctrine:schema:validate

  • I think cascading exclusion can be maintained. The problem would even define the country’s acronym as a foreign key of the table of states, I think the Doctrine does not handle it well (besides not being a recommended practice).

  • @Rodrigorigotti Excellent, already solved the problem, I put Joincollumn by the id itself and kept onDelete,his tip to use Doctrine:schema:validate was spectacular, I did not have the habit of using. Now how do we do with this post? The error was lack of attention even in the mapping and lack of knowledge about foreign key in Doctrine. Will you post an answer or how we do with this post? we close?

  • I’ll write an answer :)

Show 1 more comment

1 answer

1


There are some errors with your data modeling and I believe the loading of fixtures may be in any way related to this:

  1. The foreign key of the table country on the table state is the country’s acronym instead of the id; this is not a very recommended practice - one should use the id table.
  2. The fixtures of countries (country.yml) is being loaded twice: on country upload and status upload. It is not necessary to create a class for each file. You can create a single class (for example, loadLocationData) and upload all the data inherent to that domain.

Also, I replicated your model here and saw that there are some problems in mapping the classes with the tables in the database. When you model a database using Doctrine, always try to use the command doctrine:schema:validate to see if there is no problem in mapping. :)

Browser other questions tagged

You are not signed in. Login or sign up in order to post.