Maintenant que la table des événements contient des données, il faut les récupérer à l'aide du EventRepository
.
Page agenda
Créer un controlleur EventController
avec une route event_agenda
accessible sur /event/agenda
.
Note: aidez-vous de la commande
make:controller
pour gagner du temps.
Pour toutes les routes dans ce controlleur, les noms commencerons par event_
et les chemins par /event
. Pour ne pas se répeter, on peut ajouter un attribut Route
au niveau de la classe:
#[Route('/event', name: 'event_')]
class EventController extends AbstractController
{
#[Route('/agenda', name: 'agenda')]
public function agenda(): Response
{
// ...
}
}
Pour récupérer les événements il faut utiliser la classe App\Repository\EventRepository
. Grâce à l'autowiring il suffit d'ajouter un argument à la méthode:
public function agenda(EventRepository $eventRepository): Response
Rappel: l'autowiring permet la récupération de services depuis le constructeur. Les controlleurs sont les seuls à le faire autrement.
Les repository possèdent 4 méthodes par défaut:
-
find()
: retourne 1 entité ounull
en cherchant par son identifiant -
findOneBy()
: retourne 1 entité ounull
selon des critères -
findAll()
: retourne toutes les entités -
findBy()
: retourne plusieurs entités selon des critères
Nous souhaitons par défaut récupérer les événements du jour, mais aucune de ces fonctions ne pourra nous servir puisque la propriété startAt
contient aussi l'heure. Cet appel ne retournerait rien car il chercherait précisément les événements dont startAt
correspond à l'instant présent:
$eventRepository->findBy([
'startAt' => new \DateTime(),
]);
Le Query Builder
Lorsque les méthodes de base ne suffisent pas, il faut en rajouter. Parmi les solutions fournies par Doctrine se trouve le Query Builder: un constructeur de requêtes.
Ouvrez /src/Repository/EventRepository.php et ajoutez une nouvelle méthode:
/**
* Retourne les événements qui commencent sur une journée précise
* @return Event[]
*/
public function findForDay(\DateTimeInterface $date): array
{
}
À l'intérieur, commencer par générer les heures de début et fin de journée:
$start = (clone $date)->setTime(0, 0);
$end = (clone $date)->setTime(23, 59);
Puis instancier le Query Builder:
// "e" sert d'alias pour l'entité courante Event
return $this->createQueryBuilder('e')
On ajoute une clause WHERE
avec des paramètres pour obtenir les événements du jour:
// ...
->where('e.startAt BETWEEN :start AND :end')
->setParameters([
'start' => $start,
'end' => $end,
])
Note: la chaîne passée à
where()
ressemble à du SQL mais il s'agit de DQL (Doctrine Query Language). Il n'est donc pas possible d'utiliser des fonctions ou syntaxes spécifiques au SGBD utilisé.
Doctrine va automatiquement convertir les objetsDateTime
pour créer la requête SQL.
Et une clause ORDER BY
pour trier chronologiquement:
->orderBy('e.startAt', 'ASC')
On termine par la récupération des résultats:
$start = (clone $date)->setTime(0, 0);
$end = (clone $date)->setTime(23, 59);
return $this->createQueryBuilder('e')
->where('e.startAt BETWEEN :start AND :end')
->setParameters([
'start' => $start,
'end' => $end,
])
->orderBy('e.startAt', 'ASC')
->getQuery()
->getResult()
;
De retour dans EventController::agenda
, appeler cette nouvelle méthode et utiliser dd()
pour en voir le résultat:
$events = $eventRepository->findForDay(new \DateTime('today'));
dd($events);
Si le tableau est vide, c'est qu'il n'y a peut-être aucun événement à la date du jour. Essayez de recharger les fixtures ou réduisez l'amplitude de
startAt
dans /fixtures/event.yaml.