Php – Symfony Array Collection as Entity Property

doctrine-ormPHPsymfony

Is there a way to associate an ArrayCollection to a database column created by an Entity?

For example, I have two entities: Household and Pet Type.

Household current has a property for Pet Type, but it expects the Pet Type object, so only one can chosen at the moment.

I'd like Household to be able to have multiple Pet Types. So instead of having to choose between a Dog or a Cat, they can choose Dog AND Cat.

I have tried doing this, but I get the following error:

Catchable Fatal Error: Argument 1 passed to
Acme\CoreBundle\Entity\Household::setPetType() must be an instance of
Acme\CoreBundle\Entity\PetType, instance of
Doctrine\Common\Collections\ArrayCollection given

I'm assuming I'd need to change property for petType in the Household entity in order to associate to more than one pet type?

Best Answer

From your description it seems that Household and PetType has a cardinality of m-to-one; that means that an Household record could have only a PetType while a PetType could be associated to more than one Household record.

From DB point of view that means foreign key into Household table. If you want to make possible a "multiple" connection between Household and PetType, you have to modify your relationship between entities.

Just an example (disclaimer: your entities could be named differently and I didn't test this code. I'm explaining here a concept, not working on runnable code as your example didn't came with snippet examples)

class Household 
{
  //some properties

  /**
   * @ORM\ManyToMany(targetEntity="PetType", inversedBy="households")
   * @ORM\JoinTable(name="household_pettype")
   */
  $pet_types;

  //some methods

  public function addPetType(PetType $petType)
  {
    $this->pet_types[] = $petType;

    return $this;
  }

  public function setPetTypes(ArrayCollection $petTypes)
  {
    $this->pet_types = $petTypes;

    return $this;
  }

  public function removePetType(PetType $petType)
  {
    $this->pet_types->removeElement($petType);
  }

  public function getPetTypes()
  {
    return $this->pet_types;
  }
}

class PetType
{
  //some properties

  /**
   * @ORM\ManyToMany(targetEntity="Household", mappedBy="pet_types")
   */
   $households;

  //some methods

  public function addHousehold(Household $household)
  {
    $this->households[] = $household;

    return $this;
  }

  public function setHouseholds(ArrayCollection $households)
  {
    $this->households = $households;

    return $this;
  }

  public function removeHousehold(Household $household)
  {
    $this->households->removeElement($household);
  }

  public function getHousehold()
  {
    return $this->households;
  }
}

After that you need to run again

php app/consolle doctrine:schema:update --force

This will update your DB schema and, because new cardinality is m-to-n, a relationship table named household_pettype will be created (that will hold only foreign keys from other two tables)

After that you could alternatively use two methods (from household point of view)

  • ->addPetType($petType); that will append a PetType object to Household collection
  • ->setPetTypes($petTypeArrayCollection); that will set in a shot all PetTypes
Related Topic