Упорядочить теги по количеству связанных статей - PullRequest
0 голосов
/ 29 августа 2018

Я хочу получить теги с соответствующими статьями. Однако цель состоит в том, чтобы упорядочить их по количеству связанных статей. Как этого добиться, используя классы QueryBuilder и repositiry? Я новичок в Symfony, и я пробовал выбирать теги с помощью DQL, но он не получал целые сущности.

Теги и статьи находятся в отношении @ManyToMany:

<?php

namespace App\Entity;

use Doctrine\Common\Collections\ArrayCollection;
use Doctrine\Common\Collections\Collection;
use Doctrine\ORM\Mapping as ORM;

/**
 * @ORM\Entity(repositoryClass="App\Repository\ArticleRepository")
 */
class Article
{
    /**
     * @ORM\Id()
     * @ORM\GeneratedValue()
     * @ORM\Column(type="integer")
     */
    private $id;

    /**
     * @ORM\Column(type="string", length=255)
     */
    private $title;

    /**
     * @ORM\Column(type="string", length=255)
     */
    private $shortDescription;

    /**
     * @ORM\Column(type="text")
     */
    private $content;

    /**
     * @ORM\Column(type="float")
     */
    private $price;

    /**
     * @ORM\ManyToOne(targetEntity="App\Entity\Category", inversedBy="articles")
     */
    private $category;

    /**
     * @ORM\ManyToMany(targetEntity="App\Entity\Tag", inversedBy="articles")
     */
    private $tags;

    /**
     * @ORM\ManyToMany(targetEntity="App\Entity\Author", inversedBy="articles")
     */
    private $authors;

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


    public function getId(): ?int
    {
        return $this->id;
    }

    public function getTitle(): ?string
    {
        return $this->title;
    }

    public function setTitle(string $title): self
    {
        $this->title = $title;

        return $this;
    }

    public function getShortDescription(): ?string
    {
        return $this->shortDescription;
    }

    public function setShortDescription(string $shortDescription): self
    {
        $this->shortDescription = $shortDescription;

        return $this;
    }

    public function getContent(): ?string
    {
        return $this->content;
    }

    public function setContent(string $content): self
    {
        $this->content = $content;

        return $this;
    }

    public function getPrice(): ?float
    {
        return $this->price;
    }

    public function setPrice(float $price): self
    {
        $this->price = $price;

        return $this;
    }

    public function getCategory(): ?Category
    {
        return $this->category;
    }

    public function setCategory(?Category $category): self
    {
        $this->category = $category;

        return $this;
    }

    /**
     * @return Collection|Tag[]
     */
    public function getTags(): Collection
    {
        return $this->tags;
    }

    public function addTag(Tag $tag): self
    {
        if (!$this->tags->contains($tag)) {
            $this->tags[] = $tag;
        }

        return $this;
    }

    public function removeTag(Tag $tag): self
    {
        if ($this->tags->contains($tag)) {
            $this->tags->removeElement($tag);
        }

        return $this;
    }

    /**
     * @return Collection|Author[]
     */
    public function getAuthors(): Collection
    {
        return $this->authors;
    }

    public function addAuthor(Author $author): self
    {
        if (!$this->authors->contains($author)) {
            $this->authors[] = $author;
        }

        return $this;
    }

    public function removeAuthor(Author $author): self
    {
        if ($this->authors->contains($author)) {
            $this->authors->removeElement($author);
        }

        return $this;
    }

}

<?php

namespace App\Entity;

use Doctrine\Common\Collections\ArrayCollection;
use Doctrine\Common\Collections\Collection;
use Doctrine\ORM\Mapping as ORM;

/**
 * @ORM\Entity(repositoryClass="App\Repository\TagRepository")
 */
class Tag
{
    /**
     * @ORM\Id()
     * @ORM\GeneratedValue()
     * @ORM\Column(type="integer")
     */
    private $id;

    /**
     * @ORM\Column(type="string", length=255)
     */
    private $name;

    /**
     * @ORM\ManyToMany(targetEntity="App\Entity\Article", mappedBy="tags")
     */
    private $articles;

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


    public function getId(): ?int
    {
        return $this->id;
    }

    public function getName(): ?string
    {
        return $this->name;
    }

    public function setName(string $name): self
    {
        $this->name = $name;

        return $this;
    }

    /**
     * @return Collection|Article[]
     */
    public function getArticles(): Collection
    {
        return $this->articles;
    }

    public function addArticle(Article $article): self
    {
        if (!$this->articles->contains($article)) {
            $this->articles[] = $article;
            $article->addTag($this);
        }

        return $this;
    }

    public function removeArticle(Article $article): self
    {
        if ($this->articles->contains($article)) {
            $this->articles->removeElement($article);
            $article->removeTag($this);
        }

        return $this;
    }

}

Мой последний метод, который я использовал в TagRepository:

public function findTagsByArticlesCount()
{
          return $this->createQueryBuilder('tag')
              ->leftJoin('tag.articles', 'article')
              ->orderBy('count(article.id)', 'DESC')
              ->getQuery()
          ->execute();
}

Ответы [ 2 ]

0 голосов
/ 29 августа 2018

Отсутствует groupBy при подсчете тегов в статьях:

$this->createQueryBuilder('tag')
    ->leftJoin('tag.articles', 'article')
    ->addSelect('COUNT(tag.id) AS tagcount')
    ->groupBy('tag.id')
    ->orderBy('tagcount', 'DESC')
    ->getQuery()
    ->execute();

Примечание: при присоединении к Articles вы получите number of tags * number of articles записей, которые необходимо сгруппировать по тегам для подсчета количества тегов в связанных статьях.

Примечание 2: Я бы предпочел использовать innerJoin вместо leftJoin, а не выбирать теги без связанных статей.

0 голосов
/ 29 августа 2018

Я смутно припоминаю похожий случай, который у меня был 2 года назад, который мне удалось разрешить с помощью столбца HIDDEN:

public function findTagsByArticlesCount()
{
    return $this->createQueryBuilder('tag')
        ->leftJoin('tag.articles', 'article')
        ->addSelect('COUNT(article.id) as HIDDEN cnt')
        ->orderBy('cnt', 'DESC')
        ->getQuery()
        ->execute();
}

Однако в настоящее время я не на своей рабочей станции, чтобы проверить это. Можешь попробовать?

Надеюсь, это поможет ...

...