0

I have a problem that removeElement function doesn't delete from database the many to many element. For understanding better, I will present my code:

class User {

  /**
 * @var Collection|CandidateSocialLink[]
 *
 * @ORM\OneToMany(targetEntity="UserSocialLink", mappedBy="user", cascade={"persist", "remove"})
 * @ORM\JoinColumn(name="user_social_link_id", referencedColumnName="id")
 *
 */
private $socialLinks;

class UserSocialLink {

   /**
   * @ORM\ManyToOne(targetEntity="User", inversedBy="socialLinks", cascade={"persist", "remove"})
   * @ORM\JoinColumn(name="user_id", referencedColumnName="id")
   * */
   private $user;

   /**
  * @ORM\ManyToOne(targetEntity="SocialLink", cascade={"persist", "remove"}))
  * @ORM\JoinColumn(name="social_link_id", referencedColumnName="id")
  *
  * */
  private $socialLink;

 }


class SocialLink {
 - frankly I don't have anything related to this relationship because I didn't want to have many things that I don't use.
}

I have a function in User:

public function removeSocialLink(UserSocialLink $removeSocialLink)
{
    if ($this->socialLinks->contains($removeSocialLink)) {
        $this->socialLinks->removeElement($removeSocialLink);
    }

    return $this;
}

And then I call this function:

public function save(CandidateInterface $candidate, array $arguments = ['flush' => true]): CandidateInterface
{
    $this->getEntityManager()->persist($candidate);

    if (true === $arguments['flush']) {
        $this->getEntityManager()->flush();
    }

    return $candidate;
}

When I return the entity after this operation, the entity doesn't have the social links, but in the db still appears. I think I'm not doing something good regarding the annotation, but what? If any of you has some opinion, please share.

IleNea
  • 569
  • 4
  • 17
  • Unclear... And no ManyToMany relation unlike what is wrote in the title... – Preciel Aug 06 '18 at 21:01
  • This is not a manyToMany relation. For a manyToMany you don't need to write a jointable-entity. Doctrine wil create a jointable automaticly. Check this out: https://www.doctrine-project.org/projects/doctrine-orm/en/2.6/reference/association-mapping.html#many-to-many-unidirectional – Frank B Aug 06 '18 at 21:03
  • Yes I know, but I have an additional column in UserSocialLink but I just didn't specify here because I thought is not necessary. So the only way for a many to many relationship to accept an additional column is 'to tranform' the many-to-many annotation into many-to-one. https://stackoverflow.com/questions/3542243/doctrine2-best-way-to-handle-many-to-many-with-extra-columns-in-reference-table – IleNea Aug 06 '18 at 21:08
  • You said "the entity doesn't have the social links, but in the db still appears", so user_social_link_id has null value on the user table or not? do you expect that user_social_link_id is set to null and also that the User social link record is deleted? – fgamess Aug 07 '18 at 06:48
  • Oh, I don't get it.. in user table I don't have any user_social_link_id, but in the others it manifests as if everything would be normal. Values and stuff. – IleNea Aug 07 '18 at 07:13

2 Answers2

0

In your case doctrine do not considers the changes you have made to socialLinks array to force the change clone the array:

public function removeSocialLink(UserSocialLink $removeSocialLink)
{
    if ($this->socialLinks->contains($removeSocialLink)) {
        $this->socialLinks->removeElement($removeSocialLink);
        $this->socialLinks = clone $this->socialLinks;
    }
    return $this;
}
0

Let's show you a manytomany relation, for example Doctor and Skill: a doctor can have many skill and a skill can choice by many doctors

Your owner side

class Doctor implements DoctorInterface
{

     /**
     * @var Collection
     *
     * @ORM\ManyToMany(targetEntity="Skill", mappedBy="doctors", cascade={"persist"})
     */
    protected $skills;

     /**
     * Don't forget initial your collection property 
     * Doctor constructor.
     */
    public function __construct()
    {
        $this->skills = new ArrayCollection();
    }

        /**
     * @return Collection
     */
    public function getSkills(): Collection
    {
        return $this->skills;
    }

    /**
     * @param SkillInterface $skill
     */
    public function addSkill(SkillInterface $skill): void
    {
        if ($this->getSkills()->contains($skill)) {

            return;
        } else {

            $this->getSkills()->add($skill);
            $skill->addDoctor($this);
        }
    }

    /**
     * @param SkillInterface $skill
     */
    public function removeSkill(SkillInterface $skill): void
    {
        if (!$this->getSkills()->contains($skill)) {

            return;
        } else {

            $this->getSkills()->removeElement($skill);
            $skill->removeDoctor($this);
        }
    }
}

Your invers side

class Skill implements SkillInterface
{   
     /**
     * @var Collection
     *
     * @ORM\ManyToMany(targetEntity="Doctor", inversedBy="skills", fetch="EXTRA_LAZY")
     */
    protecte    

    /**
     * Skill constructor.
     */
    public function __construct()
    {
        $this->doctors = new ArrayCollection();
    }

    /**
     * @return Collection
     */
    public function getDoctors(): Collection
    {
        return $this->doctors;
    }

    /**
     * @param DoctorInterface $doctor
     */
    public function addDoctor(DoctorInterface $doctor): void
    {
        if ($this->getDoctors()->contains($doctor)) {

            return;
        } else {

            $this->getDoctors()->add($doctor);
        }
    }

    /**
     * @param DoctorInterface $doctor
     */
    public function removeDoctor(DoctorInterface $doctor): void
    {
        if (!$this->getDoctors()->contains($doctor)) {

            return;
        } else {

            $this->getDoctors()->removeElement($doctor);
        }
    }
}
Farshadi
  • 143
  • 1
  • 12