Accéder au contenu principal

Application : les routes de notre plateforme

Application : les routes de notre plateforme

Construction des routes

Revenons à notre plateforme d'échange. Maintenant que nous savons créer des routes, je vous propose de faire un premier jet de ce que seront nos URL. Voici les routes que je vous propose de créer, libre à vous d'en changer.
Page d'accueil
On souhaite avoir une URL très simple pour la page d'accueil : /platform. Comme /platform est défini comme préfixe lors du chargement des routes de notre bundle, le path de notre route « / ». Cette page va lister les dernière annonces. Mais on veut aussi pouvoir parcourir les annonces plus anciennes, donc il nous faut une notion de page. En ajoutant le paramètre facultatif {page}, nous aurons :
/platform
page = 1
/platform/1
page = 1
/platform/2
page = 2
C'est plutôt joli, non ? Voici la route :

# src/OC/PlatformBundle/Resources/config/routing.yml

oc_platform_home:
    path:      /{page}
    defaults:  { _controller: OCPlatformBundle:Advert:index, page: 1 }
    requirements:
        page: \d*

Page de visualisation d'une annonce
Pour la page de visualisation d'une annonce, la route est très simple. Il suffit juste de bien mettre un paramètre {id} qui nous servira à récupérer la bonne annonce côté contrôleur. Voici la route :

# src/OC/PlatformBundle/Resources/config/routing.yml

oc_platform_view:
    path:      /advert/{id}
    defaults:  { _controller: OCPlatformBundle:Advert:view }
    requirements:
        id: \d+

Ajout, modification et suppression
Les routes sont simples :
# src/OC/PlatformBundle/Resources/config/routing.yml

oc_platform_add:
    path:      /add
    defaults:  { _controller: OCPlatformBundle:Advert:add }

oc_platform_edit:
    path:      /edit/{id}
    defaults:  { _controller: OCPlatformBundle:Advert:edit }
    requirements:
        id: \d+

oc_platform_delete:
    path:      /delete/{id}
    defaults:  { _controller: OCPlatformBundle:Advert:delete }
    requirements:
        id: \d+

Récapitulatif

Voici le code complet de notre fichier src/OC/PlatformBundle/Resources/config/routing.yml :

# src/OC/PlatformBundle/Resources/config/routing.yml

oc_platform_home:
    path:      /{page}
    defaults:  { _controller: OCPlatformBundle:Advert:index, page: 1 }
    requirements:
        page: \d*

oc_platform_view:
    path:      /advert/{id}
    defaults:  { _controller: OCPlatformBundle:Advert:view }
    requirements:
        id: \d+

oc_platform_add:
    path:      /add
    defaults:  { _controller: OCPlatformBundle:Advert:add }

oc_platform_edit:
    path:      /edit/{id}
    defaults:  { _controller: OCPlatformBundle:Advert:edit }
    requirements:
        id: \d+

oc_platform_delete:
    path:      /delete/{id}
    defaults:  { _controller: OCPlatformBundle:Advert:delete }
    requirements:
        id: \d+

N'oubliez pas de bien ajouter le préfixe /platform lors de l'import de ce fichier, dans app/config/routing.yml :

 # app/config/routing.yml

oc_platform:
    resource: "@OCPlatformBundle/Resources/config/routing.yml"
    prefix:   /platform

Application : le contrôleur de notre plateforme

 

Construction du contrôleur

Notre plateforme est un bundle plutôt simple. Pour le moment nous manipulons principalement les annonces, on va donc mettre toutes nos actions dans un seul contrôleur « Advert ». Plus tard, nous pourrons éventuellement créer d'autres contrôleurs.
Malheureusement, on ne connaît pas encore tous les services indispensables à la création des pages. À ce point du cours, on ne sait pas encore réaliser de formulaire, manipuler les annonces dans la base de données, ni même créer de vrais templates.
Pour l'heure, notre contrôleur sera donc très simple. On va créer le squelette de toutes les actions que l'on a mises dans nos routes. Je vous remets sous les yeux nos routes, et on enchaîne sur le contrôleur :

# src/OC/PlatformBundle/Resources/config/routing.yml

oc_platform_home:
    path:      /{page}
    defaults:  { _controller: OCPlatformBundle:Advert:index, page: 1 }
    requirements:
        page: \d*

oc_platform_view:
    path:      /advert/{id}
    defaults:  { _controller: OCPlatformBundle:Advert:view }
    requirements:
        id: \d+

oc_platform_add:
    path:      /add
    defaults:  { _controller: OCPlatformBundle:Advert:add }

oc_platform_edit:
    path:      /edit/{id}
    defaults:  { _controller: OCPlatformBundle:Advert:edit }
    requirements:
        id: \d+

oc_platform_delete:
    path:      /delete/{id}
    defaults:  { _controller: OCPlatformBundle:Advert:delete }
    requirements:
        id: \d+

Et le contrôleur « Advert » :

<?php

// src/OC/PlatformBundle/Controller/AdvertController.php

namespace OC\PlatformBundle\Controller;

use Symfony\Bundle\FrameworkBundle\Controller\Controller;
use Symfony\Component\HttpFoundation\Request;
use Symfony\Component\HttpKernel\Exception\NotFoundHttpException;

class AdvertController extends Controller
{
  public function indexAction($page)
  {
    // On ne sait pas combien de pages il y a
    // Mais on sait qu'une page doit être supérieure ou égale à 1
    if ($page < 1) {
      // On déclenche une exception NotFoundHttpException, cela va afficher
      // une page d'erreur 404 (qu'on pourra personnaliser plus tard d'ailleurs)
      throw new NotFoundHttpException('Page "'.$page.'" inexistante.');
    }

    // Ici, on récupérera la liste des annonces, puis on la passera au template

    // Mais pour l'instant, on ne fait qu'appeler le template
    return $this->render('OCPlatformBundle:Advert:index.html.twig');
  }

  public function viewAction($id)
  {
    // Ici, on récupérera l'annonce correspondante à l'id $id

    return $this->render('OCPlatformBundle:Advert:view.html.twig', array(
      'id' => $id
    ));
  }

  public function addAction(Request $request)
  {
    // La gestion d'un formulaire est particulière, mais l'idée est la suivante :

    // Si la requête est en POST, c'est que le visiteur a soumis le formulaire
    if ($request->isMethod('POST')) {
      // Ici, on s'occupera de la création et de la gestion du formulaire

      $request->getSession()->getFlashBag()->add('notice', 'Annonce bien enregistrée.');

      // Puis on redirige vers la page de visualisation de cettte annonce
      return $this->redirect($this->generateUrl('oc_platform_view', array('id' => 5)));
    }

    // Si on n'est pas en POST, alors on affiche le formulaire
    return $this->render('OCPlatformBundle:Advert:add.html.twig');
  }

  public function editAction($id, Request $request)
  {
    // Ici, on récupérera l'annonce correspondante à $id

    // Même mécanisme que pour l'ajout
    if ($request->isMethod('POST')) {
      $request->getSession()->getFlashBag()->add('notice', 'Annonce bien modifiée.');

      return $this->redirect($this->generateUrl('oc_platform_view', array('id' => 5)));
    }

    return $this->render('OCPlatformBundle:Advert:edit.html.twig');
  }

  public function deleteAction($id)
  {
    // Ici, on récupérera l'annonce correspondant à $id

    // Ici, on gérera la suppression de l'annonce en question

    return $this->render('OCPlatformBundle:Advert:delete.html.twig');
  }
}


À retenir

L'erreur 404
Je vous ai donné un exemple qui vous montre comment déclencher une erreur 404. C'est quelque chose que l'on fera souvent, par exemple dès qu'une annonce n'existera pas, qu'un argument ne sera pas bon (page = 0), etc. Lorsque l'on déclenche cette exception, le noyau l'attrape et génère une belle page d'erreur 404. Vous pouvez aller voir l'annexe « Comment personnaliser ses pages d'erreur ».
La définition des méthodes
Nos méthodes vont être appelées par le noyau : elles doivent donc respecter le nom et les arguments que nous avons définis dans nos routes et se trouver dans le scope « public ». Vous pouvez bien entendu rajouter d'autres méthodes, par exemple pour exécuter une fonction que vous réutiliserez dans deux actions différentes. Dans ce cas, vous ne devez pas les suffixer de « Action » (afin de ne pas confondre).

Testons-le

Naturellement, seules les actions index et voir vont fonctionner, car nous n'avons pas créé les templates associés (ce sera fait dans le prochain chapitre). Cependant, nous pouvons voir le type d'erreur que Symfony2 nous génère dans ce cas.
Allez sur la page de suppression d'une annonce, à l'adresse http://localhost/Symfony/web/app_dev.php/platform/delete/5. Vous pouvez voir que l'erreur est très explicite et nous permet de voir directement ce qui ne va pas. On a même les logs en dessous de l'erreur : on peut voir tout ce qui a fonctionné avant que l'erreur ne se déclenche. Notez par exemple le log n°1 :

INFO - Matched route "oc_platform_delete" (parameters: "_controller": "OC\PlatformBundle\Controller\AdvertController::deleteAction", "id": "5", "_route": "oc_platform_delete") 
 
On voit que c'est bien la bonne route qui est utilisée, super ! On voit aussi que le paramètre id est bien défini à 5 : re-super !
On peut également tester notre erreur 404 générée manuellement lorsque ce paramètre page est à 0. Allez sur http://localhost/Symfony/web/app_dev.php/platform/0, et admirez notre erreur. Regardez entre autres la toolbar (voir figure suivante).
 


Très pratique pour vérifier que tout est comme on l'attend ! Vous pouvez également voir quelle est la ligne exacte qui a généré l'exception.

 

Application : les templates de notre plateforme


Revenons à notre plateforme. Faites en sorte d'avoir sous la main le contrôleur que l'on a réalisé au chapitre précédent. Le but ici est de créer tous les templates que l'on a utilisés depuis le contrôleur, ou du moins son squelette. Étant donné que l'on n'a pas encore accès à la bas de données, on va faire avec des variables vides : cela va se remplir par la suite, mais le fait d'employer des variables vides va nous permettre dès maintenant de construire le template.
Pour encadrer tout ça, nous allons utiliser le modèle d'héritage sur trois niveaux : layout général, layout du bundle et template.

Layout général

La théorie
Comme évoqué précédemment, le layout est la structure HTML de notre site avec des blocs aux endroits stratégiques pour permettre aux templates qui hériteront de ce dernier de personnaliser la page. On va ici créer une structure simple ; je vous laisse la personnaliser si besoin est. Pour les blocs, pareil pour l'instant, on fait simple : un bloc pour le body et un bloc pour le titre.


La pratique
Commençons par faire le layout général de l'application, la vue située dans le répertoire /app. Voici le code exemple que je vous propose :
{# app/Resources/views/layout.html.twig #}
<!DOCTYPE html>
<html>
<head>
  <meta charset="utf-8">
  <meta name="viewport" content="width=device-width, initial-scale=1">
  <title>{% block title %}OC Plateforme{% endblock %}</title>
  {% block stylesheets %}
    {# On charge le CSS de bootstrap depuis le site directement #}
    <link rel="stylesheet" href="//maxcdn.bootstrapcdn.com/bootstrap/3.2.0/css/bootstrap.min.css">
  {% endblock %}
</head>
<body>
  <div class="container">
    <div id="header" class="jumbotron">
      <h1>Ma plateforme d'annonces</h1>
      <p>
        Ce projet est propulsé par Symfony2,
        et construit grâce au MOOC OpenClassrooms et SensioLabs.
      </p>
      <p>
        <a class="btn btn-primary btn-lg" href="http://fr.openclassrooms.com/informatique/cours/developpez-votre-site-web-avec-le-framework-symfony2">
          Participer au MOOC »
        </a>
      </p>
    </div>
    <div class="row">
      <div id="menu" class="col-md-3">
        <h3>Les annonces</h3>
        <ul class="nav nav-pills nav-stacked">
          <li><a href="{{ path('oc_platform_home') }}">Accueil</a></li>
          <li><a href="{{ path('oc_platform_add') }}">Ajouter une annonce</a></li>
        </ul>
        <h4>Dernières annonces</h4>
        {{ render(controller("OCPlatformBundle:Advert:menu", {'limit': 3})) }}
      </div>
      <div id="content" class="col-md-9">
        {% block body %}
        {% endblock %}
      </div>
    </div>
    <hr>
    <footer>
      <p>The sky's the limit © {{ 'now'|date('Y') }} and beyond.</p>
    </footer>
  </div>
  {% block javascripts %}
    {# Ajoutez ces lignes JavaScript si vous comptez vous servir des fonctionnalités du bootstrap Twitter #}
    <script src="//ajax.googleapis.com/ajax/libs/jquery/1.11.1/jquery.min.js"></script>
    <script src="//maxcdn.bootstrapcdn.com/bootstrap/3.2.0/js/bootstrap.min.js"></script>
  {% endblock %}
</body>
</html>
Voici les lignes qui contiennent un peu de Twig :
  • Ligne 9 : création du bloc « title » avec « OC Plateforme » comme contenu par défaut ;
  • Lignes 36 et 37 : utilisation de la fonction {{ path }} pour faire des liens vers d'autres routes ;
  • Ligne 41 : inclusion de la méthode menu du contrôleur Advert du bundle OCPlatformBundle, avec l'argument nombre défini à 3 ;
  • Lignes 44 et 45 : création du bloc « body » sans contenu par défaut.
Et voilà, nous avons notre layout général ! Pour pouvoir tester nos pages, il faut maintenant s'attaquer au layout du bundle.

Layout du bundle

La théorie
Comme on l'a dit, ce template va hériter du layout général, ajouter la petite touche personnelle au bundle Advert, puis se faire hériter à son tour par les templates finaux. En fait, il ne contient pas grand-chose. Laissez courir votre imagination, mais, moi, je ne vais rajouter qu'une balise <h1>, vous voyez ainsi le mécanisme et pouvez personnaliser à votre sauce.
La seule chose à laquelle il faut faire attention, c'est au niveau du nom des blocs que ce template crée pour ceux qui vont l'hériter. Une bonne pratique consiste à préfixer le nom des blocs par le nom du bundle courant. Regardez le code et vous comprendrez.
La pratique
Voici ce que j'ai mis pour le layout du bundle :
{# src/OC/PlatformBundle/Resources/views/layout.html.twig #}
{% extends "::layout.html.twig" %}
{% block title %}
  Annonces - {{ parent() }}
{% endblock %}
{% block body %}
  {# On définit un sous-titre commun à toutes les pages du bundle, par exemple #}
  <h1>Annonces</h1>
  <hr>
  {# On définit un nouveau bloc, que les vues du bundle pourront remplir #}
  {% block ocplatform_body %}
  {% endblock %}
{% endblock %}
On a ajouté un <h1> dans le bloc body, puis créé un nouveau bloc qui sera personnalisé par les templates finaux. On a préfixé le nom du nouveau bloc pour le body afin d'avoir un nom unique pour notre bundle.

Les templates finaux

Advert/index.html.twig
C'est le template de la page d'accueil. On va faire notre première boucle sur la variable {{ listAdverts }}. Cette variable n'existe pas encore, on va modifier le contrôleur juste après.
{# src/OC/PlatformBundle/Resources/views/Advert/index.html.twig #}
{% extends "OCPlatformBundle::layout.html.twig" %}
{% block title %}
  Accueil - {{ parent() }}
{% endblock %}
{% block ocplatform_body %}
  <h2>Liste des annonces</h2>
  <ul>
    {% for advert in listAdverts %}
      <li>
        <a href="{{ path('oc_platform_view', {'id': advert.id}) }}">
          {{ advert.title }}
        </a>
        par {{ advert.author }},
        le {{ advert.date|date('d/m/Y') }}
      </li>
    {% else %}
      <li>Pas (encore !) d'annonces</li>
    {% endfor %}
  </ul>
{% endblock %}
Pas grand-chose à dire, on a juste utilisé les variables et expressions expliquées dans ce chapitre.
Afin que cette page fonctionne, il nous faut modifier l'action indexAction() du contrôleur pour passer une variable {{ listAdverts }} à cette vue. Pour l'instant, voici juste de quoi se débarrasser de l'erreur :
<?php
// src/OC/PlatformBundle/Controller/AdvertController.php
// Dans l'action indexAction() :
return $this->render('OCPlatformBundle:Advert:index.html.twig'array(
  'listAdverts' => array()
));


Si vous n'aviez pas rajouté l'action menu du contrôleur tout à l'heure, voici comment le faire, et aussi comment l'adapter à l'argument qu'on lui a passé cette fois-ci :
<?php
// src/OC/PlatformBundle/Controller/AdvertController.php
  public function menuAction($limit)
  {
    // On fixe en dur une liste ici, bien entendu par la suite
    // on la récupérera depuis la BDD !
    $listAdverts = array(
      array('id' => 2'title' => 'Recherche développeur Symfony2'),
      array('id' => 5'title' => 'Mission de webmaster'),
      array('id' => 9'title' => 'Offre de stage webdesigner')
    );
    return $this->render('OCPlatformBundle:Advert:menu.html.twig'array(
      // Tout l'intérêt est ici : le contrôleur passe
      // les variables nécessaires au template !
      'listAdverts' => $listAdverts
    ));
  }
Avec sa vue associée :
{# src/OC/PlatformBundle/Resources/views/Advert/menu.html.twig #}
<ul class="nav nav-pills nav-stacked">
  {% for advert in listAdverts %}
    <li>
      <a href="{{ path('oc_platform_view', {'id': advert.id}) }}">
        {{ advert.title }}
      </a>
    </li>
  {% endfor %}
</ul>
Vous voulez voir des annonces au lieu du message pas très drôle comme quoi il n'y a pas encore d'annonce ? Voici un tableau d'annonces à ajouter temporairement dans la méthode indexAction(), que vous pouvez passer en paramètre à la méthode render(). C'est un tableau pour l'exemple, par la suite il faudra bien sûr récupérer les annonces depuis la base de données !
<?php
// src/OC/PlatformBundle/Controller/AdvertController.php
// …
public function indexAction($page)
  {
    // ...
    // Notre liste d'annonce en dur
    $listAdverts = array(
      array(
        'title'   => 'Recherche développpeur Symfony2',
        'id'      => 1,
        'author'  => 'Alexandre',
        'content' => 'Nous recherchons un développeur Symfony2 débutant sur Lyon. Blabla…',
        'date'    => new \Datetime()),
      array(
        'title'   => 'Mission de webmaster',
        'id'      => 2,
        'author'  => 'Hugo',
        'content' => 'Nous recherchons un webmaster capable de maintenir notre site internet. Blabla…',
        'date'    => new \Datetime()),
      array(
        'title'   => 'Offre de stage webdesigner',
        'id'      => 3,
        'author'  => 'Mathieu',
        'content' => 'Nous proposons un poste pour webdesigner. Blabla…',
        'date'    => new \Datetime())
    );
    // Et modifiez le 2nd argument pour injecter notre liste
    return $this->render('OCPlatformBundle:Advert:index.html.twig'array(
      'listAdverts' => $listAdverts
    ));
  }
Rechargez la page, et profitez du résultat. ;) Si vous avez bien ajouté le CSS de Twitter, le résultat devrait ressembler à la figure suivante.

Le rendu de notre blog
Le rendu de notre site

Advert/view.html.twig
Il ressemble beaucoup à index.html.twig sauf qu'on passe à la vue une variable {{ advert }} contenant une seule annonce, et non plus une liste d'annonces. Voici un code par exemple :
{# src/OC/PlatformBundle/Resources/view/Advert/view.html.twig #}
{% extends "OCPlatformBundle::layout.html.twig" %}
{% block title %}
  Lecture d'une annonce - {{ parent() }}
{% endblock %}
{% block ocplatform_body %}
  <h2>{{ advert.title }}</h2>
  <i>Par {{ advert.author }}, le {{ advert.date|date('d/m/Y') }}</i>
  <div class="well">
    {{ advert.content }}
  </div>
  <p>
    <a href="{{ path('oc_platform_home') }}" class="btn btn-default">
      <i class="glyphicon glyphicon-chevron-left"></i>
      Retour à la liste
    </a>
    <a href="{{ path('oc_platform_edit', {'id': advert.id}) }}" class="btn btn-default">
      <i class="glyphicon glyphicon-edit"></i>
      Modifier l'annonce
    </a>
    <a href="{{ path('oc_platform_delete', {'id': advert.id}) }}" class="btn btn-danger">
      <i class="glyphicon glyphicon-trash"></i>
      Supprimer l'annonce
    </a>
  </p>
{% endblock %}
Et l'adaptation du contrôleur bien évidemment :
<?php
// src/OC/PlatformBundle/Controller/AdvertController.php
// …
public function viewAction($id)
  {
    $advert = array(
      'title'   => 'Recherche développpeur Symfony2',
      'id'      => $id,
      'author'  => 'Alexandre',
      'content' => 'Nous recherchons un développeur Symfony2 débutant sur Lyon. Blabla…',
      'date'    => new \Datetime()
    );
    return $this->render('OCPlatformBundle:Advert:view.html.twig'array(
      'advert' => $advert
    ));
  }
La figure suivante représente le rendu de /platform/advert/1.

Visualisation d'un article
Visualisation d'une annonce

Advert/edit.html.twig et add.html.twig
Ceux-ci contiennent une inclusion de template. En effet, rappelez-vous, j'avais pris l'exemple d'un formulaire utilisé pour l'ajout, mais également la modification. C'est notre cas ici, justement. Voici donc le fichier edit.html.twig :
{# src/OC/PlatformBundle/Resources/views/Advert/edit.html.twig #}
{% extends "OCPlatformBundle::layout.html.twig" %}
{% block title %}
  Modifier une annonce - {{ parent() }}
{% endblock %}
{% block ocplatform_body %}
  <h2>Modifier une annonce</h2>
  {{ include("OCPlatformBundle:Advert:form.html.twig") }}
  <p>
    Vous éditez une annonce déjà existante, merci de ne pas changer
    l'esprit générale de l'annonce déjà publiée.
  </p>
  <p>
    <a href="{{ path('oc_platform_view', {'id': advert.id}) }}" class="btn btn-default">
      <i class="glyphicon glyphicon-chevron-left"></i>
      Retour à l'annonce
    </a>
  </p>
{% endblock %}
Le template add.html.twig lui ressemble énormément, je vous laisse donc le faire.
Quant à form.html.twig, on ne sait pas encore le faire, car il demande des notions de formulaire, mais faisons déjà sa structure pour le moment (vous devriez déjà l'avoir) :
{# src/OC/PlatformBundle/Resources/views/Advert/form.html.twig #}
<h3>Formulaire d'annonce</h3>
{# On laisse vide la vue pour l'instant, on la comblera plus tard
   lorsqu'on saura afficher un formulaire. #}
<div class="well">
  Ici se trouvera le formulaire.
</div>
Une chose importante ici : dans ce template, il n'y a aucune notion de bloc, d'héritage, etc. Ce template est un électron libre : vous pouvez l'inclure depuis n'importe quel autre template.
Et, bien sûr, il faut adapter le contrôleur pour passer la variable $advert  :
<?php
// src/OC/PlatformBundle/Controller/AdvertController.php
  public function editAction($idRequest $request)
  {
    // ...
    
    $advert = array(
      'title'   => 'Recherche développpeur Symfony2',
      'id'      => $id,
      'author'  => 'Alexandre',
      'content' => 'Nous recherchons un développeur Symfony2 débutant sur Lyon. Blabla…',
      'date'    => new \Datetime()
    );
    return $this->render('OCPlatformBundle:Advert:edit.html.twig'array(
      'advert' => $advert
    ));
  }
Ainsi, /platform/edit/1 nous donnera la figure suivante.

Modification d'un article
Modification d'une annonce

Pour conclure

Et voilà, nous avons généré presque tous nos templates. Bien sûr, ils sont encore un peu vides, car on ne sait pas utiliser les formulaires ni récupérer les annonces depuis la base de données. Mais vous savez maintenant les réaliser et c'était une étape importante ! Je vais vous laisser créer les templates manquants ou d'autres afin que vous vous fassiez la main. Bon code !
Cela termine ce chapitre : vous savez afficher avec mise en forme le contenu de votre site. Vous avez maintenant presque toutes les billes en main pour réaliser un site internet. Bon, OK, c'est vrai, il vous manque encore des concepts clés tels que les formulaires, la base de données, etc. Mais vous maîtrisez pleinement la base du framework Symfony2, et apprendre ces prochains concepts sera bien plus facile !
Pour plus d'informations concernant Twig et ses possibilités, n'hésitez pas à lire la documentation officielle.

En résumé

  • Un moteur de templates tel que Twig permet de bien séparer le code PHP du code HTML, dans le cadre de l'architecture MVC ;
  • La syntaxe {{ var }}affiche la variable var ;
  • La syntaxe {% if %} fait quelque chose, ici une condition ;
  • Twig offre un système d'héritage (via {% extends %}) et d'inclusion (via {{ include() }} et {{ render() }}) très intéressant pour bien organiser les templates ;
  • Le modèle triple héritage est très utilisé pour des projets avec Symfony2.

Commentaires

Posts les plus consultés de ce blog

Zimbra install let's encrypt

 https://inguide.in/how-to-install-free-ssl-certificate-on-zimbra-mail-server/ Je change le domaine  ingu.pw In the article  Install Zimbra Mail Server o n CentOS 8, we learned to install Zimbra on CentOS. This article discusses the steps required to install the Let’s Encrypt free SSL certificate in Zimbra. Installing Free SSL Certificate on Zimbra: Method 1 This method is a proven one though you have to manually do all the steps. Another method discussed below is partially automatic, which might come in handy if you didn’t encounter any error during installation (working at the time of writing this article). So, let’s begin with method 1. First of all, add  epel repository  to the server 1 [root@mail ~]# yum -y install epel-release Install snapd Now, install  snapd  package with the following command 1 [root@mail ~]# sudo yum install snapd After the above step, you need to enable snapd. 1 [root@mail ~]# sudo systemctl enable --now snapd.socket Sometim...

Open Media Vault NAS change password

Known Root Password Login to the OMV using the root user and the current password via SSH or Console enter the following command passwd root The new password is now active. Unknown Root Password, but Admin Access to OMV GUI is Available In this scenario we still can help ourselves with the GUI. The method we use is, that we create a cron job for the root user which then resets the password. Navigate to System -> Cron Jobs Press the +Add button UN-tick the enabled box, so that the cronjob does not run automatically. put into the command field the following line, replace newpasswd with your password: echo "root:newpasswd" | chpasswd press okay select the newly created cron job Click the run button. in the opening window click the start button. It will shortly deactivate and activate again. open ssh or console and login as root with your new password. Root and Admin Password Unknown If you do not know the root password, you need to boot with a Li...

cPanel DDOS attack - Mitigate Slowloris Attacks - mod_qos

Apache mod_evasive Mod_evasive is a module available for the Apache HTTP server that can automatically block attacks by rate-limiting any IP that sends too many requests in a short time. Start by installing the module from WHM’s  EasyApache 4  interface. Select the  Currently Installed Packages  profile, search for  mod_evasive  in the  Apache Modules  section, and then install it. The default settings are good for most servers, but you can tweak them further by editing the configuration file  /etc/apache2/conf.d/300-mod_evasive.conf . You can also whitelist specific IP addresses or classes, so legitimate requests are not blocked. Configure CSF to block attacks While  mod_evasive  works very well, it only protects the Apache webserver. In order to harden other services as well, you can install the free  ConfigServer Security & Firewall  (CSF), which also includes a WHM plugin. As the  root  user, install CSF ...