Routing et requête

Nous avons déjà abordé la notion de routing.

Dans notre projet, c’est Symfony qui gère nos routes (i.e. nos “chemins d’URL”).

Par exemple, quand on se rend sur localhost:8080/, c’est Symfony qui grâce à nos annotations @Route que c’est la méthode index de notre HomeController qui doit être exécuté.

Le but va être ici de faire une route et une méthode de controlleur pour nos pages d’articles de blog.

On voudrait donc une URL du type /articles/{id de l'article}, ainsi /articles/1 nous emmènera sur la page de l’article ayant l’id 1 dans la base de données et celui-ci n’existe pas, nous devrons avoir une erreur 404.

Petit exemple

Dans votre HelloController, ajoutez la méthode suivante

/**
 * @Route("/hello/{name}", name="hello_name")
 */
public function helloName()
{
    return new Response("Hello !");
}

et ajoutez l’import use Symfony\Component\HttpFoundation\Response;

Essayez d’aller sur la page localhost:8080/hello/test.

Vous êtes aller sur /hello/john et cela vous a ammener sur la page correspondant à /hello/{name}.

C’est parce {name} est un paramètre, mais comment le récupérer ?

1ère méthode : Avec l’objet Request

Modifiez votre code comme ceci

/**
 * @Route("/hello/{name}", name="hello_name")
 */
public function helloName(Request $request)
{
    return new Response('Hello ' . $request->get('name'));
}

et ajoutez l’import use Symfony\Component\HttpFoundation\Request;

Actualisez la page, vous devriez voir apparaître Hello john.

C’est une première piste pour notre page d’article de blog.

2ème méthode : avec des paramètres de méthode

Changez à nouveau votre code par celui-ci

/**
 * @Route("/hello/{name}", name="hello_name")
 */
public function helloName($name)
{
    return new Response('Hello ' . $name);
}

Ici, comme votre route contient un paramètre name, Symfony essaye de passer la valeur à un argument de la méthode qui s’appelle $name.

Encore mieux non ?

Appliquons ça à notre page article

Créez ArticleController grâce à la commande php bin/console make:controller

Rennomez la méthode index en show et ajouter la route /articles/{id}

Récupérez l’id en utilisant la méthode que vous préfèrez.

Injectez le repository des articles dans ce nouveau controller et avec la méthode find($id), récupérez l’article en base de données.

Dans le dossier templates/article, rennommez également le index.html.twig en show.html.twig et adaptez dans ce nouveau template le fichier post.html du template que nous avions téléchargé au chapitre sur Twig.

Passez votre article au template et afficher les données de votre article dans cette nouvelle page.

Enfin, générez les liens vers les articles dans home/index.html.twig avec la méthode url(). Cherchez dans la documentation comment vous pouvez passer un paramètre à cette méthode pour qu’elle génère l’URL avec l’id à l’intérieur.

Si tout va bien, vous pouvez aller sur la page d’accueil et cliquer sur un lien : vous devriez arriver sur lma page de détail d’un article !

Quelque chose ne va pas ?

A ce moment là, il se peut que votre page ne ressemble à rien ☹

C’est parce vos fichiers CSS sont chargés relativement à la nouvelle URL par votre navigateur et du coup, les URL vers les fichiers CSS, JS et les images ne sont pas bonnes.

Pour résoudre ça : composer require symfony/asset

Ce paquet va vous forunir une méthode Twig bien pratique : asset('path/to/my/file.css')

Avec cette méthode, pas besoin de se soucier de ce genre de problèmes, elle va géjnérer des URL absolues vers vos fichiers statiques.

Utilisez cette méthode pour tous vos fichiers CSS, JS et vos images.

Ce paquet peut faire beaucoup plus que ça, consulter la documentation si vous voulez en savoir plus.

Et maintenant, elle est belle votre page article ?

Normalement, vous devriez avoir une belle page article.

Mais on peut encore réduire le nombre de lignes dans notre controlleur grâce au ParamConverter !

D’abord, ajoutez le Bundle qui inclu le ParamConverter composer require sensio/framework-extra-bundle

Changez la signature de votre méthode par

/**
 * @Route("/articles/{id}", name="show")
 */
public function show(Article $article)

Et supprimez dans le corps de la méthode l’appel au repository, pour ne laisser que le return $this->render(...)

Actualisez votre page Article, normalement, rien n’a changé.

Symfony a tout fait à votre place !

Il a pris le nom de votre paramètre (ici id) et a été chercher un Article (grâce au typage) qui possède un id avec comme valeur, celle contenue dans l’URL !

Donc si vous changez id par test dans l’annotation @Route, ça ne marchera pas, car Article ne possède pas de champ test.

Ici aussi, vous pouvez aller dans le Profiler pour regarder la requête SQL générée par Doctrine.