1

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?

2
  • 2
    In your case Entity has Many to Many relation. ( One household can have many PetType and One PetType can be in many household). Post your entity classes for more explanation. Commented Jun 21, 2015 at 4:36
  • Thanks. I typically post as much code as possible, but there's an NDA in place on this project, so I'm not sure how much info I can divulge. Using your input and the answer below, I was able to get this working. Thanks! Commented Jun 21, 2015 at 14:55

1 Answer 1

3

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
Sign up to request clarification or add additional context in comments.

1 Comment

Thanks! I figured as much. I was 99% sure I'd need a relation table, but just wanted to verify. I've got the solution by implementing a number of elements from your answer.

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.