[英]Symfony: Is there any way to render a twig template using a relative path to the template?
[英]Symfony 4 : DRY and performant way to render OneToMany relation entities in same twig template
我需要在同一樹枝模板中渲染兩個關系實體Salarie和Contrat的某些屬性,基本上是從所有Salarie記錄中渲染出來的,而僅是從 附加到每個Salarie的 特定 Contrat中 渲染出來的 。
薪金實體
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 ! -->
{% endfor %}
如標准系統:冠軍收集過濾中所述,我還嘗試了從教義( 標准 )獲得的出色功能
public function getLastContrat()
{
$criteria = Criteria::create()
->orderBy(['dateDebut' => 'DESC']);
->setMaxResults(1);
return $this->contrats->matching($criteria)->current();
}
然后在Twig中,我可以{{ dump(salarie.lastContrat) }}
返回期望的對象。
但是沒有辦法從那里獲取屬性。 {{ salarie.lastContrat.someProperty }}
不起作用。
必須看到{{ salarie.lastContrat }}
打印出Contrat __toString方法返回的事實。
我不會公開更多嘗試,所以請問我的問題是: 如何從getLastContrat()
上方呈現屬性值,什么是實現這一目標的最干和最有效的方法?
除了循環,您還可以提取第一個元素:
{% if not empty salarie.contrats %}
{% set contrat = salarie.contrats[0] %}
{# you can also use salarie.contrats|first #}
{{ contrat.departement }}
{% endif %}
即使只有一個元素, Criteria
也會返回一個Collection
,因此您可以應用與上述相同的原理。
盡管您也可以在將結果傳遞給樹枝之前將結果提取到控制器中,然后將它們作為實體而不是集合進行傳遞。 在上面的存儲庫中:
/**
* @returns Contrat|null
*/
public function getLastContrat()
{
$criteria = Criteria::create()
->orderBy(['dateDebut' => 'DESC'])
->setMaxResults(1);
return $this->contrats->matching($criteria)->first();
}
您可以做的另一件事是將要呈現的相關對象的另一個變量傳遞到模板中(本例中的最后一項)。 因此,在控制器中,您首先要獲取Salarie對象,然后獲取所需的約束。 它不是最DRY的解決方案,但是如果您沒有更多需要/想要重用一段代碼的用例,則不能真正應用DRY。 因此,這種方法很好,因為您的實體不需要任何標准邏輯,而且性能很好,因為您只獲取所需的信息。
如果您沒有更多可以重用代碼的用例,則不要過度優化,等待情況發生,然后您可以根據實際需求尋找共享代碼的方法,不相信:)
干杯!
聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.