Published on

doctrine教程12---过滤关系集合

原创文章,转载时需取得本人同意并注明来源
Authors
  • doctrine教程12---过滤关系集合
    Name
    langziyang
    Twitter

doctrine教程12---过滤关系集合

我们修改一下模板:

{% extends 'base.html.twig' %}

{% block body %}


<h1 class="text-3xl p-5 text-center my-4 font-semibold"><span class="fa {{ category.iconKey }}"></span> {{ categoryName }} Fortunes</h1>
<div class="flex justify-center mb-16 px-4">
    <div>
        <table class="table-auto border mb-6">
            <thead class="bg-slate-500 text-white">
                <tr>
                    <th class="border p-4">
                        Fortunes
                    </th>
                    <th class="border p-4">
                        Print History ({{ fortunesPrinted|number_format }} total, {{ fortunesAverage|number_format }} average)
                    </th>
                </tr>
            </thead>
            <tbody>
            {% for fortuneCookie in category.fortuneCookies %}
                <tr class="hover:bg-slate-200">
                    <td class="border p-4">
                        {{ fortuneCookie.fortune }}
                    </td>
                    <td class="border p-4">
                        {{ fortuneCookie.numberPrinted }} printed since {{ fortuneCookie.createdAt|date('M jS Y') }}
                    </td>
                </tr>
            {% endfor %}
            </tbody>
        </table>
        <a class="text-slate-700 hover:text-slate-900 font-semibold" href="{{ path('app_homepage') }}"><i class="fa fa-angle-double-left"></i> Back to Fortune Categories</a>
    </div>
</div>
    
        
    
{% endblock %}

但是我们的FortuneCookie有一个$discontinued属性,我们只需要取值为false的数据,我们可以单独创建一个查询,但这太费事了,我们先去控制器把 findWithFortunesJoin修改为find(),这只是为了更容易看到我们接下来要做的事情

打开Category.php找到getFortuneCookies()方法,在下面添加一个getFortuneCookiesStillInProduction()的新方法,接下来我们可以在方法里 循环$this->fortuneCookies as $fortuneCookie,这是最简单的,但是如果我们想取其中10个结果,首先得取出所有数据,可能成百上千个,太浪费了。

我们真正想做的是选择Doctrine查询时添加一个WHERE discontinued = false,很简单,我们在方法添加下面的代码

public function getFortuneCookiesStillInProduction(): Collection
    {
        $criteria = Criteria::create()
            ->andWhere(Criteria::expr()->eq('discontinued', false));
        return $this->fortuneCookies->matching($criteria);
    }

然后我们去twig上修改

{% for fortuneCookie in category.fortuneCookiesStillInProduction %}
                    <tr class="hover:bg-slate-200">
                        <td class="border p-4">
                            {{ fortuneCookie.fortune }}
                        </td>
                        <td class="border p-4">
                            {{ fortuneCookie.numberPrinted }} printed since {{ fortuneCookie.createdAt|date('M jS Y') }}
                        </td>
                    </tr>
                {% endfor %}

代码是不是正常工作了?是不是特别简单?缺点是查询的逻辑放在了实体文件而不是储库中,但我们其实可以移过去

打开FortuneCookieRepository.php,添加一个方法createFortuneCookiesStillInProductionCriteria()返回Criteria对象

注意这是一个静态方法,因为我们在Category.php里访问存储库对象,回到Category.php修改代码

public function getFortuneCookiesStillInProduction(): Collection
    {
        $criteria = FortuneCookieRepository::createFortuneCookiesStillInProductionCriteria();
        return $this->fortuneCookies->matching($criteria);
    }

在首页我们也有同样的需求,统计的都是所有数据,把({{ category.fortuneCookies|length }})修改为({{ category.fortuneCookiesStillInProduction|length }})

完全工作了,但这并不是最好的部分,如果我们希望在网站上的任何地方都这样过滤呢?