Faites votre propre contrôleur

Vers la fin du précédent tutoriel, nous avions créé une route unique qui, une fois accédée, rendrait le contenu de notre template (par exemple hello_page.html.twig ), et hello_page.html.twig cela comme le corps de la réponse.

Bien que nous n'ayons pas eu besoin de créer notre propre classe Controller ou méthode de contrôleur (dans les versions antérieures de Symfony, souvent appelées Action), nous avons utilisé un contrôleur fourni par Symfony ( TemplateController ) et Action ( templateAction ) dans les coulisses .

J'ai aussi mentionné que dans 99% des cas, vous ne travailleriez probablement pas de cette façon, dans le monde réel.

Pourtant, il est intéressant de connaître cette fonctionnalité, et cela nous a également épargné d'avoir à faire quelque chose de plus que ce que nous avions à faire pour commencer.

Laisse maintenant créer notre propre classe de contrôleur, et dans ce contrôleur nous créerons notre toute première méthode de contrôleur.

Faire une classe de contrôleur

Il y a un tas de façons de créer une nouvelle classe de contrôleur.

Nous pourrions:

  • Copiez et collez le code des documents
  • Taper manuellement tout à partir de la mémoire
  • Créer et utiliser un modèle dynamique
  • Copier / coller une classe de contrôleur à partir d'un projet existant

Etc.

Ou, et peut-être plus facile, nous pouvons en make un:

php bin/console

# ...

 make
  make:auth                               Creates an empty Guard authenticator
  make:command                            Creates a new console command class
  make:controller                         Creates a new controller class
  make:entity                             Creates a new Doctrine entity class
  make:form                               Creates a new form class
  make:functional-test                    Creates a new functional test class
  make:serializer:encoder                 Creates a new serializer encoder class
  make:subscriber                         Creates a new event subscriber class
  make:twig-extension                     Creates a new Twig extension class
  make:unit-test                          Creates a new unit test class
  make:validator                          Creates a new validator and constraint class
  make:voter                              Creates a new security voter class

Cela signifie que nous pouvons taper php bin/console make:controller , et suivre l'invite pour créer un contrôleur de base, et une action «demo».

Essayons:

php bin/console make:controller

 Choose a name for your controller class (e.g. BravePuppyController):
 > WelcomeController

 created: src/Controller/WelcomeController.php

  Success! 

 Next: Open your new controller class and add some pages!

Maintenant, si nous regardons dans notre application, sous le répertoire src/Controller , nous voyons en effet WelcomeController.php .

Le contenu de WelcomeController.php est:

<?php

namespace App\Controller;

use Sensio\Bundle\FrameworkExtraBundle\Configuration\Route;
use Symfony\Bundle\FrameworkBundle\Controller\Controller;
use Symfony\Component\HttpFoundation\Response;

class WelcomeController extends Controller
{
    /**
     * @Route("/welcome", name="welcome")
     */
    public function index()
    {
        // replace this line with your own code!
        return $this->render('@Maker/demoPage.html.twig',
          'path' => str_replace($this->getParameter('kernel.project_dir').'/', '', __FILE__)
        ]);
    }
}

J'ai pris la légère liberté d'ajuster la formulation de la déclaration de return pour faciliter la lecture. Le code généré sera sur une seule ligne.

Il y a un tas de choses intéressantes qui se passent dans ce code, et même s'il serait cool de plonger dans chaque partie, cela rendrait les choses plus complexes qu'elles ne le devraient à ce stade.

Ce que je vais suggérer, c'est que nous faisons deux changements rapides au code généré:

  • Supprimez l' use Symfony\Component\HttpFoundation\Response; ligne
  • Le changement extends Controller pour extends AbstractController

Suppression de l' use Symfony\Component\HttpFoundation\Response; est assez facile. C'est inutilisé, donc nous pouvons simplement supprimer toute la ligne. Je ne suis pas sûr pourquoi il est fourni dans la sortie générée, et il ne peut pas être dans les versions futures.

Ensuite, changez:

use Symfony\Bundle\FrameworkBundle\Controller\Controller;

à:

use Symfony\Bundle\FrameworkBundle\Controller\AbstractController;

Et mettre à jour:

class WelcomeController extends Controller

à:

class WelcomeController extends AbstractController

Bien que ce ne soit pas quelque chose que nous couvrirons immédiatement, il s'agit d' une pratique recommandée pour les contrôleurs Symfony. Nous allons couvrir ce que ce changement fait un peu plus tard.

Routin 'Tootin'

Pour le reste de cette vidéo, nous allons nous concentrer sur cette nouvelle route qui est maintenant disponible dans notre application, grâce à l'annotation de routage générée pour nous:

  /** * @Route("/welcome", name="welcome") */ public function index() 

Cette annotation de routage mappe la route ou le path de /welcome vers la méthode d' index .

Geek Trivia : Si vous venez de Symfony 2 ou Symfony 3, vous pouvez vous demander ce qu'il est advenu du suffixe Action , comme dans indexAction . C'est possible car notre WelcomeController est un service .

Nous pouvons vérifier que cette route est correctement configurée en exécutant à nouveau la commande bin/console debug:router :

bin/console debug:router
 -------------------------- -------- -------- ------ ----------------------------------- 
  Name                       Method   Scheme   Host   Path                               
 -------------------------- -------- -------- ------ ----------------------------------- 
  welcome                    ANY      ANY      ANY    /welcome                           
  _twig_error_test           ANY      ANY      ANY    /_error/{code}.{_format}           
  _wdt                       ANY      ANY      ANY    /_wdt/{token}                      
  _profiler_home             ANY      ANY      ANY    /_profiler/                        
  _profiler_search           ANY      ANY      ANY    /_profiler/search                  
  _profiler_search_bar       ANY      ANY      ANY    /_profiler/search_bar              
  _profiler_phpinfo          ANY      ANY      ANY    /_profiler/phpinfo                 
  _profiler_search_results   ANY      ANY      ANY    /_profiler/{token}/search/results  
  _profiler_open_file        ANY      ANY      ANY    /_profiler/open                    
  _profiler                  ANY      ANY      ANY    /_profiler/{token}                 
  _profiler_router           ANY      ANY      ANY    /_profiler/{token}/router          
  _profiler_exception        ANY      ANY      ANY    /_profiler/{token}/exception       
  _profiler_exception_css    ANY      ANY      ANY    /_profiler/{token}/exception.css   
  hello_page                 ANY      ANY      ANY    /hello                             
 -------------------------- -------- -------- ------ ----------------------------------- 

Ce n'est pas évident immédiatement, mais la nouvelle route est au sommet, et notre route existante est au fond.

Si vous ne l'avez pas déjà fait, http://127.0.0.1:8000/welcome -vous sur http://127.0.0.1:8000/welcome et consultez votre nouvelle sortie de contrôleur:

symfony 4 make: sortie du contrôleur

Jusqu'ici tout va bien.

Changer les choses

Définissons notre nouvelle action de contrôleur pour répondre à la racine de notre site. En d'autres termes, configurons ce contrôleur pour répondre à / .

Ceci est facilement réalisé. Nous avons juste besoin de mettre à jour l'annotation de routage:

  /** * @Route("/", name="welcome") */ public function index() 

Ne pas hésiter à re-vérifier la sortie de bin/console debug:router lors de modifications. Si vous voyez la modification dans la sortie de votre console, vous savez que Symfony a compris et accepté votre modification.

Ensuite, plutôt que de restituer le modèle généré, créons-en un nouveau.

Nous allons utiliser Bootstrap 4. N'hésitez pas à changer cela pour être n'importe quel framework CSS que vous aimez. Ou sautez simplement le CSS, si les visuels ne sont pas votre tasse de thé.

Nous allons commencer par créer un nouveau template dans un sous-répertoire du répertoire templates :

 mkdir templates/welcome 

Et dans le nouveau répertoire templates/welcome , nous allons créer un nouveau template, index.html.twig :

 touch templates/welcome/index.html.twig 

Ce nom correspond à celui de notre méthode Controller, mais ce n'est pas obligatoire. Sur les plus gros projets, une convention de nommage comme celle-ci vous facilitera la vie. Utilisez ce que vous voulez, bien sûr.

Bootstrap offre quelques exemples de templates , et j'ai légèrement personnalisé l'un d'entre eux pour ce qui suit:

<!doctype html>
<html lang="en">
<head>
    <meta charset="utf-8">
    <meta name="viewport" content="width=device-width, initial-scale=1, shrink-to-fit=no">
    <meta name="description" content="">
    <meta name="author" content="">

    <title>Let's Explore Symfony 4</title>

    <!-- Bootstrap core CSS -->
    <link rel="stylesheet"
          href="https://maxcdn.bootstrapcdn.com/bootstrap/4.0.0-beta.3/css/bootstrap.min.css"
          integrity="sha384-Zug+QiDoJOrZ5t4lssLdxGhVrurbmBWopoEl+M6BdEfwnCJZtKxi1KgxUyJq13dy"
          crossorigin="anonymous">
</head>

<body>
    <header>
        <nav class="navbar navbar-expand-sm navbar-dark bg-dark">
            <div class="container">

                <a class="navbar-brand" href="#">Home</a>

                <div class="collapse navbar-collapse">
                    <ul class="navbar-nav mr-auto">
                        <li class="nav-item">
                            <a class="nav-link" href="/hello">Hello Page</a>
                        </li>
                    </ul>
                </div>
            </div>

        </nav>
    </header>

    <main role="main" class="container main">
        <div>
            <h1>Let's Explore Symfony 4</h1>
            <p class="lead">Lorem ipsum dolor sit amet, consectetur adipiscing elit. Cras rutrum sapien mauris, venenatis
                facilisis neque tincidunt vel. Maecenas vel felis vel turpis scelerisque eleifend. Fusce nec purus egestas,
                efficitur nisi ac, ultrices nulla. Pellentesque eu mollis tortor, in mollis nisl. Maecenas rhoncus quam non
                lacinia mollis.</p>
        </div>
    </main>
</body>
</html>

Ce qui devrait ressembler à ceci:

permet d'explorer la page symfony 4

Ce serait bien d'abaisser le h1 quelques pixels. Nous pourrions ajouter cela en tant qu'élément de style directement au modèle, mais un meilleur moyen consiste à déplacer les styles dans un fichier séparé.

Nous avons besoin que nos fichiers de style soient accessibles au public, ce qui signifie qu'ils doivent vivre dans le répertoire public .

 mkdir public/css touch public/css/custom-styles.css 

Rappelez-vous, le touch est juste un moyen ringard de créer un nouveau fichier vide avec le nom donné, à partir de la CLI. N'hésitez pas à créer le répertoire, et le fichier de votre IDE.

Plutôt que de h1 directement la balise h1 , je vais "remonter" à l'élément main et appliquer mon style à la classe .main :

 .main { margin-top: 20px; } 

Cela ne fonctionnera pas seulement . Nous devons indiquer à notre modèle notre feuille de style.

Je vais ajouter mon entrée de feuille de style personnalisée juste au-dessus de la balise de fermeture. Cela garantit que le CSS Bootstrap est exécuté en premier, puis mes styles personnalisés sont appliqués "en haut".

<!doctype html>
<html lang="en">
<head>
    <meta charset="utf-8">
    <meta name="viewport" content="width=device-width, initial-scale=1, shrink-to-fit=no">
    <meta name="description" content="">
    <meta name="author" content="">

    <title>Let's Explore Symfony 4</title>

    <!-- Bootstrap core CSS -->
    <link rel="stylesheet" href="{{ asset('css/custom-style.css') }}" />
</head>

Notez que la feuille de style n'utilise pas un chemin codé en dur. Au lieu de cela, nous pouvons utiliser la fonction d'assistance d' asset pour permettre au Component Asset de déterminer où se trouvent nos ressources, ce qui est très utile lorsque nos configurations de templates deviennent plus compliquées.

En utilisant symfony/website-skeleton nous avons déjà accès à une bibliothèque de gestion des ressources frontales plus complète: Webpack Encore . Nous n'utilisons pas cela pour le moment. Vous n'avez pas toujours besoin de tout ce que le framework fournit, alors ne vous sentez pas obligé d'utiliser tout ce qu'il y a de brillant. Utilisez simplement les bits dont vous avez besoin.

Essayez-le vous-même

Les meilleures pratiques de Symfony 4 pour la gestion des actifs frontaux (pensez notamment à JS et CSS) sont d'utiliser Webpack Encore.

Essayez d'utiliser la documentation , en passant de notre approche CSS actuelle à l'utilisation de Webpack Encore.

Quels autres outils / logiciels avez-vous besoin d'installer?

Cela valait-il la peine d'un effort supplémentaire?

Pensez à laisser un commentaire ci-dessous en partageant vos opinions et vos expériences.

De meilleurs liens

Dans notre barre de navigation, nous avons ajouté quelques liens:

 <nav class="navbar navbar-expand-sm navbar-dark bg-dark">
        <div class="container">

            <a class="navbar-brand" href="/">Home</a>

            <div class="collapse navbar-collapse">
                <ul class="navbar-nav mr-auto">
                    <li class="nav-item">
                        <a class="nav-link" href="/hello">Hello Page</a>
                    </li>
                </ul>
            </div>
        </div>
    </nav>

Nous avons Home, qui utilise le site root ( / ), et notre page Hello sur /hello .

Rappelez-vous plus tôt comment nous avons changé le chemin de l'itinéraire de /welcome à / , mais gardé le nom de la route comme welcome ?

Eh bien, l'une des plus belles choses à propos de Twig est que si nous ne codons pas en dur nos liens, mais que nous utilisons le nom du lien, nous pouvons facilement changer nos chemins sans nous soucier de casser notre site.

Ce que cela signifie dans la pratique est qu'au lieu d'utiliser:

<a class="navbar-brand" href="/">Home</a>

Nous ferions mieux avec:

<a class="navbar-brand" href="{{ path('welcome') }}">Home</a>

De même, pour la page Hello, nous ferions mieux de passer de:

<a class="nav-link" href="/hello">Hello Page</a>

à:

<a class="nav-link" href="{{ path('hello_page') }}">Hello Page</a>

Ce qui signifie que notre barre de navigation révisée ressemble à ceci:

 <nav class="navbar navbar-expand-sm navbar-dark bg-dark">
        <div class="container">

            <a class="navbar-brand" href="{{ path('welcome') }}">Home</a>

            <div class="collapse navbar-collapse">
                <ul class="navbar-nav mr-auto">
                    <li class="nav-item">
                        <a class="nav-link" href="{{ path('hello_page') }}">Hello Page</a>
                    </li>
                </ul>
            </div>
        </div>
    </nav>

Le path et l' asset sont que quelques-unes des nombreuses fonctions disponibles dans vos modèles Twig. Certains vous utiliserez plus que d'autres.

Vous pouvez tester à quel point cela est utile en changeant le path de votre page hello_page pour autre chose que /hello . Dès que vous faites cela, et actualisez votre navigateur, vous verrez les mises à jour de lien automatiquement pour utiliser le nouveau chemin. Cela continuera à fonctionner tant que vous ne modifiez pas le name l'itinéraire. Si vous changez le nom, assurez-vous de mettre à jour tous les appels de fonction de path dans vos modèles.

À propos de la page Hello

Un problème un peu flagrant en ce moment est que si nous naviguons vers la racine du site ( / ) nous avons une belle page Bootstrap 4 avec notre barre de navigation, un peu de style, et nous nous sentons très bien dans notre peau.

Ensuite, nous cliquons sur le lien "Hello_page" et le boom, pas de style, pas de barre de navigation, et la seule solution est de cliquer sur le bouton "retour".

Ne serait-il pas plus agréable si notre page "Hello", et toutes les pages suivantes que nous ajoutons, ont toutes réutilisé la même mise en page de base?

C'est sûr, Kent.

Voyons comment nous pouvons faire exactement cela, et plus, dans le tutoriel suivant.