- Published on
symfony教程之实体关系优化
原创文章,转载时需取得本人同意并注明来源
- Authors
-
-
- Name
- langziyang
-
我们在用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里调用这个方法试一试