Home > database >  url valid but view not loading
url valid but view not loading

Time:04-15

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 '])]

  • Related