Ordonner les entrées par champ de date de matrice multiple
J'ai une section avec des formations. Dans chaque entrée de formation, il y a un champ de matrice où nous ajoutons un nouveau bloc avec une date de formation, un lieu, etc. Ainsi, chaque formation a plusieurs blocs de matrice.
Lorsque j'exécute une requête d'entrée et que j'obtiens tous les champs de date de la matrice à l'intérieur, je peux le sortir comme ceci:
- Formation 1
- 1 octobre 2020
- 5 octobre 2020
- Formation 2
- 5 octobre 2020
- 10 octobre 2020
- Formation 3
- 7 octobre 2020
- 10 octobre 2020
Maintenant, je voudrais regrouper et classer les formations par date comme ceci:
- 1 octobre 2020
- Formation 1
- 5 octobre 2020
- Formation 1
- Formation 2
- 7 octobre 2020
- Formation 3
- 10 octobre 2020
- Formation 2
- Formation 3
Je suis proche mais je n'arrive pas à trier les dates correctement. Le modèle génère actuellement:
- 1 octobre 2020
- Formation 1
- 5 octobre 2020
- Formation 1
- Formation 2
- 10 octobre 2020
- Formation 2
- Formation 3
- 7 octobre 2020
- Formation 3
Le code que j'ai en ce moment:
{# Query entries that have training dates #}
{% set allEntries = craft.entries
.section('trainings')
.trainingDates(':notempty:')
.all() %}
{# Merge all training dates in an array #}
{% set startDates = [] %}
{% for entry in allEntries %}
{% for training in entry.trainingDates.all() %}
{% if training.startDate | date('d mm Y') not in startDates %}
{% set startDates = startDates | push(training.startDate | date('d mm Y')) %}
{% endif %}
{% endfor %}
{% endfor %}
{# Show all trainings grouped by date #}
<ul>
{% for startDate in startDates %}
<li>
<h2>{{ startDate }}</h2>
<ul>
{% for entry in allEntries %}
{% for date in entry.trainingDates.all() %}
{% if date.startDate | date('d mm Y') == startDate %}
<li><a href="{{ entry.url }}" title="{{ entry.title }}">{{ entry.title }}</a></li>
{% endif %}
{% endfor %}
{% endfor %}
</ul>
</li>
{% endfor %}
</ul>
Une idée sur la façon de trier le tableau par date? Et cela peut probablement être beaucoup plus facile. Si vous avez des conseils, j'aimerais avoir de vos nouvelles! :-)
Réponses
La réponse rapide et simple serait d'ajouter simplement le sortfiltre Twig à votre tableau startDates. par exemple:
{# Query entries that have training dates #}
{% set allEntries = craft.entries
.section('trainings')
.with('trainingDates')
.trainingDates(':notempty:')
.all()
%}
{# Merge all training dates in an array #}
{% set startDates = [] %}
{% for entry in allEntries %}
{% for training in entry.trainingDates %}
{% if training.startDate | date('d mm Y') not in startDates %}
{% set startDates = startDates | push(training.startDate | date('d mm Y')) %}
{% endif %}
{% endfor %}
{% endfor %}
{# Show all trainings grouped by date#}
<ul>
{% for startDate in startDates|sort %}
<li>
<h2>{{ startDate }}</h2>
<ul>
{% for entry in allEntries %}
{% for date in entry.trainingDates %}
{% if date.startDate | date('d mm Y') == startDate %}
<li><a href="{{ entry.url }}" title="{{ entry.title }}">{{ entry.title }}</a></li>
{% endif %}
{% endfor %}
{% endfor %}
</ul>
</li>
{% endfor %}
</ul>
(J'ai également ajouté un chargement impatient pour améliorer les performances).
Vous pouvez potentiellement attaquer le problème dans la direction opposée en utilisant une requête d'élément matrixblock comme celle-ci:
{# Query matrix blocks that have training dates #}
{% set matrixBlocksQuery = craft.matrixBlocks().field('trainingDates') %}
{% set uniqueDatesSorted = matrixBlocksQuery.all()|map(block => block.startDate|date('d mm Y'))|unique|sort %}
{# Query entries that have training dates #}
{% set allEntries = craft.entries
.section('trainings')
.with('trainingDates')
.trainingDates(':notempty:')
.all()
%}
{# Show all trainings grouped by date#}
<ul>
{% for startDate in uniqueDatesSorted %}
<li>
<h2>{{ startDate }}</h2>
<ul>
{% for entry in allEntries %}
{% for date in entry.trainingDates %}
{% if date.startDate|date('d mm Y') == startDate %}
<li><a href="{{ entry.url }}" title="{{ entry.title }}">{{ date.id }}{{ entry.title }}</a></li>
{% endif %}
{% endfor %}
{% endfor %}
</ul>
</li>
{% endfor %}
</ul>
... mais pour être honnête, je pense que je préfère votre approche, car elle est plus lisible et ne nécessite pas de .all()requête supplémentaire pour obtenir les dates
J'ai chargé une base de données avec plus de 50 formations et le tri était à nouveau erroné. Et j'ai compris pourquoi.
J'ai poussé toutes les dates dans un tableau avec le format de date comme date ('d mm Y'). Les dates seraient le 03 novembre 2020, le 17 octobre 2020, le 01 décembre 2020, etc. Les modèles utilisaient les deux premiers nombres pour trier. Les inscriptions ont donc commencé en décembre, puis en novembre et en octobre.
J'ai changé le format de date à ce jour («c») et maintenant toutes les entrées sont bien triées. Plus tard dans la boucle, j'ai affiché la date de début avec {{startDate | date ("j mm Y")}}.
Donc, quiconque essaie de faire de même, date ('c') fait l'affaire.