Published on

symfony教程之实体关系优化

原创文章,转载时需取得本人同意并注明来源
Authors
  • symfony教程之实体关系优化
    Name
    langziyang
    Twitter

我们在用symfony做开发时,关系映射对我们的开发会有非常方便的作用,比如分类与文章的对应关系中,我们可以在分类中直接取出对应的文章。以下是两个实体的代码:

class Category{
  /**
     * @var Collection<int, Article>
     */
    #[ORM\OneToMany(targetEntity: Article::class, mappedBy: 'category', orphanRemoval: true)]
    #[ORM\OrderBy(['onTop' => 'DESC', 'position' => "ASC", "createdAt" => 'DESC'])]
    private Collection $articles;

public function getArticles(): Collection
    {
        return $this->articles;
    }

    public function addArticle(Article $article): static
    {
        if (!$this->articles->contains($article)) {
            $this->articles->add($article);
            $article->setCategory($this);
        }

        return $this;
    }

    public function removeArticle(Article $article): static
    {
        if ($this->articles->removeElement($article)) {
            // set the owning side to null (unless already changed)
            if ($article->getCategory() === $this) {
                $article->setCategory(null);
            }
        }

        return $this;
    }
}
class Article
{
    #[ORM\ManyToOne(inversedBy: 'articles')]
    #[ORM\JoinColumn(nullable: false, options: ['comment' => '文章分类'])]
    private ?Category $category = null;
    public function getCategory(): ?Category
    {
        return $this->category;
    }

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

        return $this;
    }
}

可以看到我们对两个实体做了关系映射,每一个分类都可以有多个文章,每一个文章只能有一个分类, 接下来我们在twig里显示这个分类:

   <div class="title">{{ category.name}}</div>
   <div class="article_list">
                        {% for article in category.articles %}
                            {{ article.title }}
                        {% endfor %}
    </div>

是不是很方便的就把文章显示出来了?不要急,我们去写一个方法,为这个分类添加两万条或以上的文章数据,然后再来刷新页面,是不是浏览器都加载不了?因为这样会把所有数据都显示并加载出来。

如果我们只显示分类名称而不显示文章信息,那么一点问题都没有,因为在doctrine的关系映射中,默认是懒加载数据,你可能会想:是不是因为我在页面上显示了两万条数据才导致变慢呢?那我们再修改一下:

<div class="article_list">
    {{ category.article.count }}
</div>

我们只需要显示有多少条文章,同样的会变得很慢。 并且我们还有一个问题:我们要做分页呢?文章有一个字段表示禁用呢?

我们可以这样做:

   #Category.php

   public function getEffectArticles(int $count = 10)
    {
        $criteria = Criteria::create();
        $criteria->andWhere(Criteria::expr()->eq('disabled', false))
            ->orderBy(['onTop' => 'DESC', 'position' => 'ASC', 'createdAt' => 'DESC'])
            ->setMaxResults($count);
        return $this->articles->matching($criteria);
    }

然后你再去twig里调用这个方法试一试