Search code examples
phpsymfonyfixturesnelmio-alice

How to setup fixtures for ArrayCollection at entity constructor in NelmioAlice


I have read and tried all the things described in this section of docs but I can't get this working. This is the constructor at entity:

public function __construct()
{
    $this->targets = new ArrayCollection();
    $this->targetBrand = new ArrayCollection();
}

And I tried to bypass using __construct: false but get this error:

[Symfony\Component\Yaml\Exception\ParseException] Unable to parse at line 11 (near " name: ").

This is how the fixtures looks like:

\PDI\PDOneBundle\Entity\Brand:
    # 3 Brand per Company
    brand{1..3}:
       __construct: false
       name: <name()>
       generic_name: <name()>
       logo_url: <imageUrl(128,128)>
       description: <paragraph()>
       isi_required: <boolean(35)>
       isi_text: <realText()>
       isi_pdf_url: <url()>
       pi_required: <boolean(35)>
       pi_text: <realText()>
       pi_pdf_url: <url()>
       inactive: <boolean(35)>
       company: @company*
       createdAt: <dateTimeThisYear()>
       updatedAt: <dateTimeThisYear()>

If I not set __construct then the error turns into this other:

[Symfony\Component\Debug\Exception\ContextErrorException] Catchable Fatal Error: Argument 1 passed to Doctrine\Common\Collections\ArrayCollection::__construct() must be of the type array, object given, called in /var/www/html/reptooln_admin/vendor/doctrine/orm/lib/Doctrine/ORM/UnitOfWork.php on line 555 and defined

What is wrong? How I should setup the fixture?

EDIT:

I have found this but how I can use that approach on the fixture I am trying to setup, can any give me some advice?

EDIT 1:

I'm a little confused because Brand is mapped to TargetBrand entity and TargetBrand is inversed by Brand entity, see entities below:

class Brand
{
    // other class properties

    /**
     * @ORM\OneToMany(targetEntity="TargetBrand" , mappedBy="brand")
     */
    protected $targetBrand;

    protected $targets;

    public function __construct()
    {
        $this->targets = new ArrayCollection();
        $this->targetBrand = new ArrayCollection();
    }

    // other class methods

    public function getTargets()
    {
        $targets = new ArrayCollection();
        foreach ($this->targetBrand as $target) {
            $targets[] = $target->getTarget();
        }

        return $targets;
    }

    public function setTargets($targets)
    {
        foreach ($targets as $target) {
            $targetBrand = new TargetBrand();
            $targetBrand->setBrand($this);
            $targetBrand->setTarget($target);
            $this->addTargetBrand($targetBrand);
        }
    }

    public function addTargetBrand($targetBrand)
    {
        $this->targetBrand[] = $targetBrand;
    }

    public function removeTargetBrand($targetBrand)
    {
        return $this->targetBrand->removeElement($targetBrand);
    }
}


class TargetBrand
{
    /**
     * @var int
     *
     * @ORM\Column(type="integer")
     */
    protected $priority;

    /**
     * @var Target
     *
     * @ORM\ManyToOne(targetEntity="Target", inversedBy="targetBrand")
     * @ORM\JoinColumn(name="targets_id", referencedColumnName="id")
     * */
    protected $target;

    /**
     * @var Brand
     *
     * @ORM\ManyToOne(targetEntity="Brand", inversedBy="targetBrand")
     * @ORM\JoinColumn(name="brands_id", referencedColumnName="id")
     * */
    protected $brand;

    public function setPriority($priority)
    {
        $this->priority = $priority;

        return $this;
    }

    public function getPriority()
    {
        return $this->priority;
    }

    public function setTarget(Target $targets = null)
    {
        $this->target = $targets;

        return $this;
    }

    public function getTarget()
    {
        return $this->target;
    }

    public function setBrand(Brand $brand)
    {
        $this->brand = $brand;

        return $this;
    }

    public function getBrand()
    {
        return $this->brand;
    }
}

If I'm running the fixtures using a set as follow:

This is the set I mention before:

$set->addFile(__DIR__.'/Territory.yml', 'yaml');
$set->addFile(__DIR__.'/Representative.yml', 'yaml');
$set->addFile(__DIR__.'/TargetBrand.yml', 'yaml');
$set->addFile(__DIR__.'/Target.yml', 'yaml');
$set->addFile(__DIR__.'/Brand.yml', 'yaml');

$set->addFile(__DIR__.'/Company.yml', 'yaml');
$set->addFile(__DIR__.'/Media.yml', 'yaml');
$set->addFile(__DIR__.'/Message.yml', 'yaml');

$set->addFile(__DIR__.'/Email.yml', 'yaml');

And setting Brand and TargetBrand fixtures as follow:

I got this error instead:

[Symfony\Component\Debug\Exception\ContextErrorException] Catchable Fatal Error: Argument 1 passed to PDI\PDOneBundle\Entity\TargetBrand::setTarget() must be an instance of PDI\PDOneBundle\Entity\Target, instance of PDI\PDOneBundle\Entity\TargetBrand given, called in /var/www/html/reptooln_admin/vendor/nelmio/alice/src/Nelmio/Alice/Loader/Base.php on line 506 and defined

\PDI\PDOneBundle\Entity\Brand:
    # 3 Brand per Company
    brand{1..3}:
       name: <name()>
       generic_name: <name()>
       logo_url: <imageUrl(128,128)>
       description: <paragraph()>
       isi_required: <boolean(35)>
       isi_text: <realText()>
       isi_pdf_url: <url()>
       pi_required: <boolean(35)>
       pi_text: <realText()>
       pi_pdf_url: <url()>
       inactive: <boolean(35)>
       company: @company*
       createdAt: <dateTimeThisYear()>
       updatedAt: <dateTimeThisYear()>
       targetBrand: @targetBrand*

\PDI\PDOneBundle\Entity\TargetBrand:
  # 10000 TargetBrand
  targetBrand{1..1000}:
      priority: <randomDigitNotNull()>
      target: @target*
      brand: @brand*

Which is the right order to load fixtures on this case?

NOTE: $targets is not need anymore so do not take care of that one


Solution

  • If you have setters defined, i.e. setTarget() and setTargetBrand() or addTarget() and addTargetBrand(), the following should work:

    \PDI\PDOneBundle\Entity\Brand:
        brand{1..3}:
           (define your brands)
    \PDI\PDOneBundle\Entity\Target:
        target{1..3}:
           (define your targets)
    \PDI\PDOneBundle\Entity\TargetBrand:
        targetBrand{1..3}:
           target: @target<current()>
           brand: @brand<current()>
    
    \PDI\PDOneBundle\Entity\Brand:
        brand{1..3}:
            (..other definitions...)
            targets: [@target1, @target2, @target3]
            targetBrand: [@targetBrand1, @targetBrand2, @targetBrand3]