How to display a list of appointments with related user data in Symfony/Twig

‘m building an appointment management system in Symfony. I have an Appointment entity that relates to User entities for both student and teacher. I want to display a list of all appointments in a Twig template, showing the student’s first name, teacher’s first name, appointment time, and location. Additionally, I want to have links to edit and delete each appointment.

Here is my setup:

appointment/index.html.twig

<?php

namespace AppController;

use SymfonyBundleFrameworkBundleControllerAbstractController;
use SymfonyComponentHttpFoundationResponse;
use SymfonyComponentRoutingAttributeRoute;
use AppEntityAppointment; 
use AppEntityClasses;
use AppEntityUser;
use DoctrineORMEntityManagerInterface; 
use AppFormAppointmentTypeForm;
use SymfonyComponentHttpFoundationRequest;


final class AppointmentController extends AbstractController
{
 
#[Route('/appointment', name: 'app_appointment')]
public function read(EntityManagerInterface $entityManager): Response
{
    //Ophalen van alle boeken
    $appointments = $entityManager->getRepository(Appointment::class)->findAll();

    //Tonen van de juiste view (renderen)
    return $this->render('appointment/index.html.twig', [
        'appointments' => $appointments,
    ]);
}

//Functie om een boek toe te voegen verder op
#[Route('/create', name: 'app_create')]
public function add(Request $request, EntityManagerInterface $entityManager): Response
{
    $form = $this->createForm(AppointmentTypeForm::class);
    $form->handleRequest($request);
    if ($form->isSubmitted() && $form->isValid()) {
        $appointment = $form->getData();
        $entityManager->persist($appointment);
        $entityManager->flush();

        $this->addFlash('success', 'Het appointment is toegevoegd');

        return $this->redirectToRoute('app_appointment');
    }

    return $this->render('appointment/create.html.twig', [
        'form' => $form
    ]);
}


#[Route('/appointment/edit/{id}', name: 'app_appointment_edit')]
public function edit(Request $request, EntityManagerInterface $entityManager, int $id): Response
{

     $appointment = $entityManager->getRepository(Appointment::class)->find($id);
    $form = $this->createForm(AppointmentTypeForm::class, $appointment);

    $form->handleRequest($request);
    if ($form->isSubmitted() && $form->isValid()) {
        $appointment = $form->getData();
        $entityManager->persist($appointment);
        $entityManager->flush();

        $this->addFlash('success', 'Het appointment is toegevoegd');

        return $this->redirectToRoute('app_appointment');
    }

    return $this->render('appointment/create.html.twig', [
        'form' => $form
    ]);
}

#IsGranted[("ROLE_ADMIN")]
#[Route('/appointment/delete/{id}', name: 'app_appointment_delete')]
public function delete(EntityManagerInterface $entityManager, Appointment $appointment): Response {
    //We bereiden het wissen voor in de database
    $entityManager->remove($appointment);

    //We voeren de statements uit (het wordt nog gedelete)
    $entityManager->flush();

    //Uiteraard zetten we een flash-message
    $this->addFlash('success', 'appointment is gewist');

    //We maken een redirect naar de route om het aangepaste boek te tonen
    return $this->redirectToRoute('app_appointment');
}

}

appointment/index.html.twig

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

{% block title %}Hello AppointmentController!{% endblock %}

{% block body %}
<style>
    .example-wrapper { margin: 1em auto; max-width: 800px; width: 95%; font: 18px/1.5 sans-serif; }
    .example-wrapper code { background:rgb(17, 99, 153); padding: 2px 6px; }
</style>




<table class="table example-wrapper">
  <thead>
    <tr>
      <th scope="col">Student</th>
      <th scope="col">Teacher</th>
      <th scope="col">Location / Time</th>
         <th scope="col">Edit</th>
          <th scope="col">Delete</th>
    </tr>
  </thead>   
  <tbody>
      {% for appointment in appointments %}
    <tr>

      <td>  {{ appointment.student.firstName }}</td>
      <td>      {{ appointment.teacher.firstName }}</td>
  <td>   {{ appointment.time|date("F jS \a\t g:ia") }}, {{ appointment.location}}</td>

 <td><a class="nav-link" href="{{path('app_appointment_edit',  {'id': appointment.id }) }}">  Edit <span class="sr-only"></span></a></td>
  <td><a class="nav-link" href="{{path('app_appointment_delete',  {'id': appointment.id} ) }}">Delete <span class="sr-only"></span></a></td>




      </td>
    </tr>
        {% endfor %}
         <td><a class="nav-link" href="{{ path('app_create') }}"> Create   <span class="sr-only"></span></a></td>
  </tbody>
</table>


{% endblock %}

appointment/create.html.twig

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

{% block title %}Hello AppointmentController!{% endblock %}

{% block body %}
<style>
    .example-wrapper { margin: 1em auto; max-width: 800px; width: 95%; font: 18px/1.5 sans-serif; }
    .example-wrapper code { background: #F5F5F5; padding: 2px 6px; }
</style>

{{ form(form) }}
{% endblock %}

appointment.php

<?php

namespace AppEntity;

use AppRepositoryAppointmentRepository;
use DoctrineORMMapping as ORM;

#[ORMEntity(repositoryClass: AppointmentRepository::class)]
class Appointment
{
    #[ORMId]
    #[ORMGeneratedValue]
    #[ORMColumn]
    private ?int $id = null;

    #[ORMManyToOne(inversedBy: 'studentAppointments')]
    private ?User $student = null;

    #[ORMManyToOne(inversedBy: 'teacherAppointments')]
    private ?User $teacher = null;

    #[ORMColumn(length: 255)]
    private ?string $location = null;

    #[ORMColumn]
    private ?DateTime $time = null;

    #[ORMColumn(length: 255)]
    private ?string $topic = null;

    public function getId(): ?int
    {
        return $this->id;
    }

    public function getStudent(): ?User
    {
        return $this->student;
    }

    public function setStudent(?User $student): static
    {
        $this->student = $student;

        return $this;
    }

    public function getTeacher(): ?User
    {
        return $this->teacher;
    }

    public function setTeacher(?User $teacher): static
    {
        $this->teacher = $teacher;

        return $this;
    }

    public function getLocation(): ?string
    {
        return $this->location;
    }

    public function setLocation(string $location): static
    {
        $this->location = $location;

        return $this;
    }

    public function getTime(): ?DateTime
    {
        return $this->time;
    }

    public function setTime(DateTime $time): static
    {
        $this->time = $time;

        return $this;
    }

    public function getTopic(): ?string
    {
        return $this->topic;
    }

    public function setTopic(string $topic): static
    {
        $this->topic = $topic;

        return $this;
    }
}