Which is the best way to 'check if exists` in many to many relationship table in Symfony3?

I have simple implementation of User -> Favourites User Articles:

Controller:

/**
 * @Route("/articles/{category}/{id}/addtofavorites", name="addToFavourites")
 */
public function addToFavourites($category, $id)
{
    $em = $this->getDoctrine()->getManager();
    $article = $em->getRepository("AppBundle:Article")->find($id);
    $user = $this->getUser();
    $user = $em->getRepository("AppBundle:User")->find($user->getId());
    $user->addFavouriteArticle($article);
    $em->persist($user);
    $em->flush();

    $test = 'true';

    return new JsonResponse($test);
}

User Entity:

<?php

namespace AppBundle\Entity;

use Doctrine\Common\Collections\ArrayCollection;
use Doctrine\ORM\Mapping as ORM;
use FOS\UserBundle\Model\User as BaseUser;

/**
 * @ORM\Entity(repositoryClass="AppBundle\Repository\UserRepository")
 * @ORM\Table(name="user")
 */
class User extends BaseUser
{
    /**
     * @ORM\Id
     * @ORM\GeneratedValue(strategy="AUTO")
     * @ORM\Column(type="integer")
     */
    protected $id;

    /**
     * @ORM\Column(type="string")
     */
    private $firstName;

    /**
     * @var favouriteArticles[]
     * @ORM\ManyToMany(targetEntity="AppBundle\Entity\Article", cascade={"all"})
     * @ORM\JoinTable(name="user_favourite_articles",
     *     joinColumns={@ORM\JoinColumn(name="user_id", referencedColumnName="id")},
     *     inverseJoinColumns={@ORM\JoinColumn(name="article_id", referencedColumnName="id")})
     */
    private $favouriteArticles;

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

    /**
     * @return favouriteArticles[]
     */
    public function getFavouriteArticles(): array
    {
        return $this->favouriteArticles->toArray();
    }

    /**
     * @param favouriteArticles[] $favouriteArticles
     */
    public function setFavouriteArticles(array $favouriteArticles): void
    {
        $this->favouriteArticles = $favouriteArticles;
    }

    /**
     * Add user
     *
     * @param \AppBundle\Entity\Article $article
     *
     * @return User
     */
    public function addFavouriteArticle(Article $article)
    {
        $this->favouriteArticles[] = $article;

        return $this;
    }

So I should change controller method to check if Article already exists in DB and Favourite button is clicked again it should remove it from DB (at the moment it just add article every time). How to do it? If it was normal table I would add in User Repository, like this:

return (boolean)$this->createQueryBuilder('u')
            ->andWhere('u.article = :article')
            ->setParameter('article', $rticle)
            ->getQuery()
            ->getOneOrNullResult();

But in this case with ManyToMany relation I don't know how and where to do it.

Upvotes: 1

Views: 1405

Answers (2)

Daniel Pysarenko
Daniel Pysarenko

Reputation: 41

Mr Zorpen wrote everything correctly, but I would have done a little differently. In my case, the method for checking "if exists" is separately from the addition. Plus, there is a check for the emptiness of the article.

/**
 * @param Article $article
 * @return bool
 */
public function isContainsArticle(Article $article)
{
    if ($this->favouriteArticles->contains($article)) {
        return true;
    }

    return false;
}

/**
 * @param Article $article
 * @return bool
 */
public function addArticle (Article $article)
{
    if (empty($article) || $this->isContainsArticle($article)) {
        return false;
    }
    $this->favouriteArticles->add($article);

    return true;
}

/**
 * @param Article $article
 */
public function removeArticle (Article $article)
{
    $this->favouriteArticles->removeElement($article);
}

Upvotes: 0

Zorpen
Zorpen

Reputation: 445

public function addFavouriteArticle(Article $article)
{
    if ($this->favouriteArticles->contains($article)) {
        return;
    }

    $article->setUser($this);
    $this->favouriteArticles[] = $article;
}

public function removeFavouriteArticle(Article $article)
{
    $this->favouriteArticles->removeElement($article);
}

This way user would never add same article to his favourites (because it aleady exists).

Upvotes: 3

Related Questions