Symfony 4:在同一枝条模板中呈现 OneToMany 关系实体的干式和高性能方式

我需要呈现两个关系实体的一些性质Salarie和Contrat,在同一树枝模板,基本上所有的Salarie记录,但只能从一个特定 Contrat 连接到每个Salarie。


实体员工


namespace App\Entity;


class Salarie

{

// ...


/**

     * @ORM\OneToMany(targetEntity="App\Entity\Contrat", mappedBy="salarie")

     * @ORM\OrderBy({"dateDebut" = "DESC"})

     */

    private $contrats;

//...

实体合同


namespace App\Entity;


class Contrat

{

// ...

/**

     * @ORM\ManyToOne(targetEntity="App\Entity\Salarie", inversedBy="contrats")

     * @ORM\JoinColumn(nullable=false)

     */

    private $salarie;

// ...

员工控制器


class SalarieController extends AbstractController

{

    /**

     * @Route("/", name="salarie_index", methods={"GET"})

     */

    public function index(SalarieRepository $salarieRepository): Response

    {

        return $this->render('salarie/index.html.twig', [

            'salaries' => $salarieRepository->findAll(), //findAllWithLastContrat(),

        ]);

    }

乍一看,我认为在 Salarie 存储库中使用自定义查询会很简单,但我一直在与连接、子查询和其他东西作斗争。这是一个纯粹的 Twig 工作解决方案,但它根本不是 DRY,因为我必须为每个属性重复它,而且我敢打赌它也会影响性能,因为当我只需要一些时,我正在查询所有 Contrat ......


<tbody class="list">

    {% for salarie in salaries %}

        <tr>

            <td>{% for contrat in salarie.contrats  %}

                  {% if loop.first %}

                    {{ contrat.departement }}

                  {% endif %}

                {% endfor %}

            </td>

            <td>{% for contrat in salarie.contrats  %}

                  {% if loop.first %}

                    {{ contrat.service }}

                  {% endif %}

                {% endfor %} 

            </td>

        </tr>

        <!-- AND SO ON ABOUT 12 TIMES ! -->


然后在 Twig 中我可以 {{ dump(salarie.lastContrat) }}返回预期的对象。

http://img4.mukewang.com/6184e4f700011c2e04690865.jpg

但是没有办法从那里获取属性。 {{ salarie.lastContrat.someProperty }}不起作用。

http://img.mukewang.com/6184e5030001f4e011420457.jpg

必须查看{{ salarie.lastContrat }}打印 Contrat __toString 方法返回内容的事实。

我不会公开更多尝试,所以请我的问题是:如何从上面呈现属性值getLastContrat()以及实现这一目标的最干燥和最高效的方法是什么?


森栏
浏览 132回答 2
2回答

杨__羊羊

您只需提取第一个元素,而不是循环:{% if not empty salarie.contrats %}&nbsp; &nbsp; {% set contrat = salarie.contrats[0] %}&nbsp; &nbsp; {# you can also use salarie.contrats|first #}&nbsp; &nbsp; {{ contrat.departement }}{% endif %}CriteriaCollection即使只有一个元素也会返回 a ,因此您可以应用与上述相同的原则。尽管您也可以在将结果传递给 twig 之前在控制器中提取结果,并将它们作为实体而不是集合传递。在上面的存储库中:/**&nbsp;* @returns Contrat|null&nbsp;*/public function getLastContrat(){&nbsp; &nbsp; $criteria = Criteria::create()&nbsp; &nbsp; &nbsp; ->orderBy(['dateDebut' => 'DESC'])&nbsp; &nbsp; &nbsp; ->setMaxResults(1);&nbsp; &nbsp; return $this->contrats->matching($criteria)->first();}

小怪兽爱吃肉

您可以做的另一件事是将另一个变量与要呈现的相关对象一起传递到模板中(在您的情况下是最后一个)。因此,在您的控制器中,您首先获取 Salarie 对象,然后获取所需的 contrat。这不是最 DRY 的解决方案,但如果您没有更多需要/想要重用一段代码的用例,您就不能真正应用 DRY。因此,这种方法很好,因为您的实体不需要任何标准逻辑,而且性能非常好,因为您只获取所需的内容。如果你没有更多的用例可能会重复使用代码,那么不要过度优化,等待情况发生,然后你可以根据实际需要寻找一种方法来共享你的代码,不相信:)
打开App,查看更多内容
随时随地看视频慕课网APP