I've been working on an online learning website for a school project. I've had trouble passing variales when clicking on a lesson, belonging to a section, inside a course. The idea is that on a course page (formation.html.twig), there's a summary of the course, and you can click on the lessons which are in a sidebar menu. It should then display a page with the same menu, and the content of the lesson showing in place of the course summary (lesson.html.twig).
I've updated the controller so the url goes: formations/consulter-formationid-sectionid-lessonid
In the view, I wrote {{ path('app_formations_lesson', {'formation':formation.id, 'section': section.id, 'id':lesson.id}) }}
It's working alright for the url and the right values show when I click, but the page refreshes and won't load the right twig view (lesson.html.twig), it loads the same view I'm currently on (formation.html.twig).
FormationsController:
#[Route('/formations/consulter-{id}', name: 'app_formations_see')]
public function see($id): Response
{
$formation = $this->doctrine->getRepository(Formation::class)->findOneById($id);
$section = $this->doctrine->getRepository(Section::class)->findAll();
$lesson = $this->doctrine->getRepository(Lesson::class)->findAll();
return $this->render('formations/formation.html.twig', [
'formation' => $formation,
'sections' => $section,
'lessons' => $lesson
]);
}
#[Route('/formations/consulter-{formation}-{section}-{id}', name: 'app_formations_lesson')]
public function seeLesson($id): Response
{
$lesson = $this->doctrine->getRepository(Lesson::class)->findOneById($id);
return $this->render('formations/lesson.html.twig', [
'lesson' => $lesson
]);
}
formation.html.twig
{% extends 'base.html.twig' %}
{% block title %}{{ formation.title }}{% endblock %}
{% block content %}
<div >
{% block sidebar %}
{% include "./formations/sidebar.html.twig" %}
{% endblock %}
<h1>{{ formation.title }} par {{ formation.user.firstname }} {{ formation.user.lastname }}</h1>
{{ formation.description }}
<hr>
<h2>Sommaire</h2>
<div >
<table >
{% for section in formation.sections %}
<thead >
<tr>
<th scope="col">{{ section.name }}</th>
</tr>
</thead>
<tbody>
{% for lesson in section.lessons %}
<tr>
<td>{{ lesson.title }}</td>
</tr>
{% endfor %}
</tbody>
{% endfor %}
</table>
</div>
</div>
{% endblock %}
lesson.html.twig
{% extends 'base.html.twig' %}
{% block title %}titre de la leçon{% endblock %}
{% block content %}
<div >
{% block sidebar %}
{% include "./formations/sidebar.html.twig" %}
{% endblock %}
<h1>Nom de la leçon</h1>
<hr>
<h2>Vidéo</h2>
<h2>Contenu</h2>
</div>
{% endblock %}
sidebar block
<!-- Sidear for lesson pages -->
<nav >
<button id="sidenav-btn" type="button" data-bs-toggle="collapse" data-bs-target="#sidebarCollapse" aria-expanded="false" aria-controls="collapseOne">
Sommaire
</button>
<div id="sidebarCollapse" aria-expanded="true">
<li >
{% for section in formation.sections %}
<ul >
<li>{{ section.name }}</li>
</ul>
<div>
{% for lesson in lessons %}
<ul >
<li><a href="{{ path('app_formations_lesson', {'formation':formation.id, 'section': section.id, 'id':lesson.id}) }}" >{{ lesson.title }}</a></li>
</ul>
{% endfor %}
</div>
{% endfor %}
</li>
<li ></li>
<li >
<ul >
<li><a href="{{path('app_formations')}}" >retour à la liste des formations</a></li>
</ul>
</li>
</div>
</nav>
Where does this issue come from? How can I display the right view? Thanks a lot!
edit: I swapped the code in the controller to match the seeLesson function first.
#[Route('/formations/consulter-{formation}-{section}-{id}', name: 'app_formations_lesson')]
public function seeLesson($id): Response
{
$formation = $this->doctrine->getRepository(Formation::class)->findOneById($id);
$section = $this->doctrine->getRepository(Section::class)->findAll();
$lesson = $this->doctrine->getRepository(Lesson::class)->findOneById($id);
return $this->render('formations/lesson.html.twig', [
'lesson' => $lesson,
'formation' => $formation,
'sections' => $section
]);
}
#[Route('/formations/consulter-{id}', name: 'app_formations_see')]
public function see($id): Response
{
$formation = $this->doctrine->getRepository(Formation::class)->findOneById($id);
$section = $this->doctrine->getRepository(Section::class)->findAll();
$lesson = $this->doctrine->getRepository(Lesson::class)->findAll();
return $this->render('formations/formation.html.twig', [
'formation' => $formation,
'sections' => $section,
'lessons' => $lesson
]);
}
CodePudding user response:
It's rendering the wrong page because your URLs are too similar.
When trying to determine what method to execute, Symfony matches the requested URL against the route definitions above the controller methods from top to bottom.
If you're requesting for example /formations/consulter-1-2-3
,
Symfony first tries to match this against /formations/consulter-{id}
.
This matches if you substitute 1-2-3
for {id}
, so it executes the see
method.
To fix you have two options:
Either switch the order of the 2 methods in your controller so that the method seeLesson
is defined above the see
method. Symfony will then first try to match against the route for the seeLesson
method.
Or keep the method order as is, but add a constraint to the {id}
parameter in the route for the see
method, to specify that the matched {id}
can only consist of digits:
#[Route('/formations/consulter-{id}', name: 'app_formations_see', requirements: ['id' => '\d '])]