我尝试使用 Symfony 创建自定义查询构建器

Posted

技术标签:

【中文标题】我尝试使用 Symfony 创建自定义查询构建器【英文标题】:I try to create a custom querybuilder with Symfony 【发布时间】:2022-01-04 18:19:40 【问题描述】:

我在这两个实体上有一个 OneToMany 关系:

Article ArticleLikes
<?php

namespace App\Entity;

use App\Repository\ArticleRepository;
use Doctrine\Common\Collections\ArrayCollection;
use Doctrine\Common\Collections\Collection;
use Doctrine\ORM\Mapping as ORM;

/**
 * @ORM\Entity(repositoryClass=ArticleRepository::class)
 */
class Article

    /**
     * @ORM\Id
     * @ORM\GeneratedValue
     * @ORM\Column(type="integer")
     */
    private $id;

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

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

    /**
     * @ORM\Column(type="datetime_immutable")
     */
    private $createdAt;

    /**
     * @ORM\ManyToOne(targetEntity=User::class, inversedBy="articles")
     * @ORM\JoinColumn(nullable=false)
     */
    private $relation;

    /**
     * @ORM\OneToMany(targetEntity=ArticleLikes::class, mappedBy="article")
     */
    private $articleLikes;

    public function __construct()
    
        $this->articleLikes = 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 getContent(): ?string
    
        return $this->content;
    

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

        return $this;
    

    public function getCreatedAt(): ?\DateTimeImmutable
    
        return $this->createdAt;
    

    public function setCreatedAt(\DateTimeImmutable $createdAt): self
    
        $this->createdAt = $createdAt;

        return $this;
    

    public function getRelation(): ?User
    
        return $this->relation;
    

    public function setRelation(?User $relation): self
    
        $this->relation = $relation;

        return $this;
    

    /**
     * @return Collection|ArticleLikes[]
     */
    public function getArticleLikes(): Collection
    
        return $this->articleLikes;
    

    public function addArticleLike(ArticleLikes $articleLike): self
    
        if (!$this->articleLikes->contains($articleLike)) 
            $this->articleLikes[] = $articleLike;
            $articleLike->setArticle($this);
        

        return $this;
    

    public function removeArticleLike(ArticleLikes $articleLike): self
    
        if ($this->articleLikes->removeElement($articleLike)) 
            // set the owning side to null (unless already changed)
            if ($articleLike->getArticle() === $this) 
                $articleLike->setArticle(null);
            
        
        return $this;
    

    /**
     * @param User $user
     * @return bool
     */
    public function isLikedByUser(User $user): bool
    
        foreach ($this->getArticleLikes() as $like)
        
            if ($like->getUser() === $user) 
                return true;
            
        
        return false;
    

<?php

namespace App\Entity;

use App\Repository\ArticleLikesRepository;
use Doctrine\ORM\Mapping as ORM;

/**
 * @ORM\Entity(repositoryClass=ArticleLikesRepository::class)
 */
class ArticleLikes

    /**
     * @ORM\Id
     * @ORM\GeneratedValue
     * @ORM\Column(type="integer")
     */
    private $id;

    /**
     * @ORM\ManyToOne(targetEntity=Article::class, inversedBy="articleLikes")
     * @ORM\JoinColumn(nullable=false)
     */
    private $article;

    /**
     * @ORM\ManyToOne(targetEntity=User::class, inversedBy="articleLikes")
     * @ORM\JoinColumn(nullable=false)
     */
    private $user;

    /**
     * @ORM\Column(type="datetime_immutable")
     */
    private $createdAt;

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

    public function getArticle(): ?Article
    
        return $this->article;
    

    public function setArticle(?Article $article): self
    
        $this->article = $article;

        return $this;
    

    public function getUser(): ?User
    
        return $this->user;
    

    public function setUser(?User $user): self
    
        $this->user = $user;

        return $this;
    

    public function getCreatedAt(): ?\DateTimeImmutable
    
        return $this->createdAt;
    

    public function setCreatedAt(\DateTimeImmutable $createdAt): self
    
        $this->createdAt = $createdAt;

        return $this;
    

Article 实体可以包含ArticleLikes 的集合。

ArticleLikes 实体中,每个赞都与Article (articleId) 以及用户字段(userId) 相关。

要检索每篇文章的点赞数,我在Article 实体中有一个方法:

/ **
 * @return Collection | ArticleLikes []
 * /
public function getArticleLikes (): Collection

    return $ this-> articleLikes;

我迷路了,因为我想创建一个查询,允许您检索最近 10 篇最受欢迎的文章(最多的是 ArticleLikes)。我不知道我是否需要进行左连接或其他操作。我该如何做这个查询?

我要检索ArticleLikes最多的10篇文章。

图片:

【问题讨论】:

您的一个编辑似乎包含解决方案。请将其作为答案发布,以便其他人可以从中受益并表明您已经解决了您的问题。 【参考方案1】:

解决办法是:

->orderBy('count(al)', 'DESC')

获取最喜欢的 10 篇文章的查询生成器:

/**
 * @return array
 *  get the 10 most liked articles
 */
public function findArticlesMostLiked(): array

    return $this->createQueryBuilder('a')
        ->select( 'a')
        ->join('a.articleLikes', 'al')
        ->groupBy('al.article')
        ->orderBy('count(al)', 'DESC')
        ->setMaxResults(10)
        ->getQuery()
        ->getResult()
        ;

【讨论】:

以上是关于我尝试使用 Symfony 创建自定义查询构建器的主要内容,如果未能解决你的问题,请参考以下文章

Symfony - 在学说查询构建器中使用 orWhere()

API REST 的 symfony 5 自定义身份验证

在 Symfony2 的查询中使用自定义 DQL 函数

Symfony2 将自定义字段添加到表单构建器

Symfony 自定义路由加载器:导入错误

Symfony |如何从控制器中的存储库访问自定义方法?