Créer un petit site rapidement avec symfony 2

Posté par Lecesne Yannick dans Symfony

Symfony

Créer un petit site rapidement avec symfony 2

Pour ce premier article sur le blog je vais essayer de vous montrer comment créer rapidement un petit site grâce au framework Symfony 2.

Avant de commencer

Pour ce tuto vous avez besoin :

  • D'avoir un serveur web installé sur sa machine
  • D'avoir des bases avec un Terminal ( sous windows vous pouvez installer le git shell et avoir certaines commandes Linux )

À la fin du tuto notre site comportera :

  • 2/3 pages statiques ou même plus si vous en avez envie ( partie 1 : Installation, configuration, système d'heritage de Twig, assets )
  • 1 page de contact ( partie 2 : mise en place d'un formulaire de contact simple )
  • 1 page actualité / blog qui sera administrable via un back-office

1.Installer Symfony 2

Tout d'abord nous devons récupérer Symfony2 sur notre machine.
Ici nous avons deux possibilités qui s'offrent à nous. La première c'est de télécharger le zip directement sur le site de Symfony.
La seconde est un peu plus complexe, est d'installer "l'installateur" de Symfony.

Pour ma part je développe sous Mac OS, j'ai donc opté pour l'installation avec l'installateur.
J'ai créé un dossier tuto-blog ou j'ai installé Symfony2.

installation de symfony

Voilà c'est à vous de décider. Pour les néophytes et les personnes qui ne sont pas très à l'aise avec le shell ( terminal ) je vous conseil le zip.
Une fois installé vous devriez avoir cette architecture dans votre dossier ( pour moi tuto-blog ).
Si vous ne voyez pas le dossier "vendor" vous devez l'installer. Pour ça il suffit de lancer la commande : php composer.phar install. Vous allez me dire 

"composer.phar" c'est quoi ?

Et bien c'est un fichier qui va se trouver à la racine de votre application et qui va vous permettre d'installer les bundles nécessaires.
Pour le récupérer vous pouvez le télécharger ici.
Vous avez du remarquer le composer.json, il s'agit de votre liste de bundle et si vous l'ouvrez vous verrez la liste des bundles de base de Symfony.
Libre à vous d'en rajouter par la suite. Par exemple, le bundle FOSUserBundle est un bundle très utilisé pour gérer les connexions / inscriptions sur votre site. Mais ce sera l'objet d'un autre tuto.

architecture de symfony2

Une fois Symfony récupéré, il faut gérer les droits sur les dossiers de cache et de logs (pour les utilisateurs de Mac ou Linux).

sudo chmod -R 777 app/cache app/logs

Ici j'utilise un simple 777 mais en prod ce n'est pas conseiller, pour en savoir plus c'est par ici.

Une fois les droits ajoutés vous devriez pouvoir visualiser votre site à l'adresse suivante : http://localhost/tuto-blog/web/app_dev.php/app/exemple

Je n'ai pas configuré de vhost pour ce site mais rien ne vous empêche de le faire, si vous savez le faire ;)
Pour les autres je ferais un petit tuto dessus pour avoir une url en local du style monsuperblog.local

Si vous vous demandez pourquoi le web/app_dev.php
-> Le dossier web/ est le seul répertoire auquel vos utilisateurs auront accès, votre vhost (nom de domaine) pointera directement sur ce répertoire. En somme, c'est la porte d'entrée de notre application.

-> app_dev.php permet d'avoir la toolbar de Symfony2 pour debugger en bas de page, j'ai un doute mais je crois ça force le refresh du cache aussi. Lors de l'appel du fichier app_dev vous êtes dans "l'environement" de dev. à l'inverse en passant par app.php vous charger l'environnement de "prod" ou autre si vous avez plusieurs environnements 
Si vous ouvrez ce fichier (web/app_dev.php), vous verrez qu'il y a une sécurité sur les adresses ip, donc si vous souhaitez y accéder quand votre site est en ligne vous pouvez ajouter votre adresse ip dans ce fichier, cela va vous permettre d'afficher les erreur de Symfony sur votre serveur de prod (le mieux c'est d'avoir une IP statique).

-> /app/exemple Si vous regardez dans le dossier src/ vous trouverez un bundle d'exemple et ceci est l'url "d'exemple" du bundle. Comment je le sais ? et bien pour connaître les routes de votre application vous pouvez lancer la commande suivante :

php app/console router:debug

Cette commande va vous listez tout le routing de votre application.

Symfony 2 est un framework qui utilise l'architecture MVC.
Pour savoir quel Controleur est appelé pour afficher la page /app/exemple vous pouvez vous aidez de la Toolbar de Symfony.

Toolbar Symfony

Ici nous pouvons voir que l'url /app/exemple appelle le controleur DefaultController et la méthode IndexAction.
Vous pouvez maintenent aller dans src/AppBundle/Controller/DefaultController.php vous trouverez la méthode IndexAction qui renvoie la vue default/index.html.twig qui se trouve dans app/Resources/views/default/index.html.twig
Personnellement je n'ai jamais utilisé le dossier app pour mes templates, je préfère garder tous mes templates à l'intérieur de mon bundle je trouve ça plus "propre" et puis si vous voulez patagez demain votre bundle se sera plus simple.

Symfony propose plusieurs format de ficheir de configuration ( dans l'exemple fourni par Symfony vous pouvez voir au dessus de la méthode IndexAction il ya le routing ecrit en Annotation) pour ma part j'aime le format Yml je le trouve plutôt clair. Maintenant ça se transforme vite en usine a gaz sur de gros site, du coup j'aurais tendance a utiliser les annotation pour de grosse appli. Maintenant pour notre petit site on va utiliser le format Yml pour nos routing.

On clean tout ça et on repart sur de bonne bases :)

Nous allons donc supprimer l'exemple de Symfony et repartir sur un code "vide", ensuite ce sera à vous de choisir si vous desirez utiliser les annotations pour le routing ou le YML ou le XML. Ce choix se fera lors de l'installation notre premier bundle, patience, patience on y est presque ;)

Commençons par supprimer le bundle AppBundle

//aller dans le répertoire de votre site, la plus part du temps sur les serveurs linux l'architecture se presente comme ça /var/www/monsite, mais sur ma machine je préfère mettre mon dossier www dans mon répertoire perso
cd /Users/yannick/www/tuto-blog

// on supprime le bundle d'exemple
rm -rf src/AppBundle

Maintenant il faut supprimer l'appel à ce bundle dans notre application, ça se passe dans le fichier app/AppKernel.php

//supprimer la ligne suivante
new AppBundle\AppBundle(),

Une fois l'appel du bundle supprimer il faut supprimer le routing de "base" de l'application qui appel le routing du bundle. Dans le fichier app/config/routing.yml Vous pouvez tous supprimer à l'intérieur.

//supprimer ou commenter les lignes suivantes
app:
resource: "@AppBundle/Controller/"
type: annotation

Si vous voulez vous pouvez supprimer le dossier app/Resources nous n'en n'aurons pas besoin.
Voilà arrivé à cette étape vous devriez avoir Symfony "vide" nous allons pouvoir maintenant créer notre propre bundle et le configurez comme nous le souhaitons.

 Créer notre bundle

Nous y sommes nous allons pouvoir générer notre premier bundle (youhou... )
Pour se faire taper la commande suivante :

php app/console generate:bundle

Si vous voulez voir toutes les commandes que propose Symfony et ses bundles vous pouvez taper la commande php app/console cela va vous montrez toutes les commandes avec leur descriptions.


Une fois lancer vous devriez avoir ceci :

Désolé pour le double screen tout ne rentrer pas sur mon ecran :)
Alors je vais vous détailler tout ça :

 

Bundle namespace: T/MainBundle

-> Ici j'ai choisi T pour "tuto", et MainBundle c'est un nom utilisé partout pour définir le bundle de base le "main" => principal, concrètement ça va me créer un bundle dans le répertoire src/T/MainBundle/...

Ensuite je confirme les propositions en faisant "entrée"

Configuration format (yml, xml, php, or annotation): yml

-> Vous vous souvenez on en a déjà parler ici vous choisissez le format qui sera utiliser pour la configuration de votre bundle, donc les routing que nous avons déjà aperçu, mais aussi les "services" ça nous le verrons un peu plus tard, pour ma part c'est le format yml pour le routing :)

Ensuite valider et dite oui a se que propose Symfony

Do you want to generate the whole directory structure [no]? yes

Confirm automatic update of your Kernel [yes]?

-> Alors ici c'est pour savoir si vous voulez que Symfony ajoute l'appel a votre bundle dans le app/AppKernel.php, si vous mettez "non" vous devez aller le mettre vous même.

Confirm automatic update of the Routing [yes]?

-> Ici il va ajouter dans le routing.yml de l'application l'url de votre bundle, en clair vous lui dite quand je tape "/" je veux que tu charges le fichier src/T/MainBundle/Resources/config/routing.yml et il ajoute ce "routing" dans le fichier app/config/routing.yml

Pour bien comprendre comment tous ceci fonctionne je vous invite à aller voir les fichiers app/AppKernel.php et app/config/routing.yml pour voir les changements, si vous vous souvenez se sont les deux fichiers ou nous avons supprimer l'appel au bundle AppBundle fourni par Symfony.
Donc vous l'aurez compris si vous voulez supprimer le bundle fraichement créer vous n'avez cas refaire la même chose que pour la suppression du AppBundle ;)

Notre première page statique avec Symfony

Méthode 1:

La première méthode pour créer une page statique est de créer un controller avec à l'intérieur une méthode qui va renvoyer notre template. Lors de la génération du bundle Symfony créer pour nous le controller src/T/MainBundle/DefaultController.php dedans vous trouverai la méthode indexAction.

 

<?php

namespace T\MainBundle\Controller;

use Symfony\Bundle\FrameworkBundle\Controller\Controller;

class DefaultController extends Controller
{
public function indexAction($name) // ici la méthode attend en paramétre "name"
{
return $this->render('TMainBundle:Default:index.html.twig', array('name' => $name)); // ici nous renvoyons dans le template src/T/MainBundle/index.html.twig la variable name
}
}

Vous devez mais comment accédez à cette page ? Car ici nous ne voyons plus le routing. Pas de panique c'est normal le routing se trouve dans le fichier src/T/MainBundle/Resources/config/routing.yml ( si vous vous souvenez bien c'est ce fichier qui est appeler dans le app/config/routing.yml )
Vous devriez avoir quelque chose comme ceci :

t_main_homepage:
path: /hello/{name}
defaults: { _controller: TMainBundle:Default:index }

Voilà ici nous pouvons voir notre url a appeler. Donc vous pouvez aller a cette url http://localhost/tuto-blog/web/app_dev.php/hello/viking
-> le mot viking est la variable {name} attendu dans l'url

Nous allons maintenant supprimer cette variable "name" car nous n'en avons pas besoin pour notre page statique. De plus nous voulons que quand nous tapons l'adresse http://localhost/tuto-blog/web/app_dev.php que ça nous dirige directement sur la page index :

t_main_homepage:
path: /
defaults: { _controller: TMainBundle:Default:index }

Ok c'est fait, ensuite il faut modifier notre controller :

<?php

namespace T\MainBundle\Controller;

use Symfony\Bundle\FrameworkBundle\Controller\Controller;

class DefaultController extends Controller
{
public function indexAction() // ici on supprime "name"
{
return $this->render('TMainBundle:Default:index.html.twig', array()); // ici on retourne ... bah rien juste la vue.
}
}

Il ne nous reste plus qu'a changer le template Twig qui se trouve dans src/T/MainBundle/Resources/views/Default/index.html.twig

Hello !

Et voilà notre première page statique avec la méthode 1 qui consiste à avoir une méthode dans notre controller pour afficher la vue.

Méthode 2

Dans cette méthode nous ne passerons pas par une méthode de notre controller, nous passerons par une méthode native de Symfony2 pour afficher notre page. Nous allons donc créer une autre page qui va s'appeler tarif.html.twig par exemple. Dupliquer la page src/T/MainBundle/Resources/views/Default/index.html.twig et renommer la tarif.html.twig. vous devriez avoir ceci :

Avec dans la page tarif écrit :

tarif !

Nous allons maintenant créer la route pour afficher cette page. pour ceux que ça intéresse voici la doc Symfony pour créer une page statique sans passer par un controller.

t_main_homepage:
path: /
defaults: { _controller: TMainBundle:Default:index }

t_main_tarif:
path: /tarif
defaults:
_controller: FrameworkBundle:Template:template
template: 'TMainBundle:Default:tarif.html.twig'

 Et voilà votre page est accessible à l'url suivante http://localhost/tuto-blog/web/app_dev.php/tarif

Maintenant c'est à vous de créer autant de pages statiques que vous le souhaitez avec l'une de ces deux méthodes. Je conseil tout de même d'utiliser la méthode 1, au moins si demain votre client vous demande d'ajouter une fonctionnalité sur cette page tout est déjà là :)

Twig et son système d'héritage

C'est bien beau d'avoir des pages mais maintenant nous allons les structurer et les styliser, pour ça nous allons utiliser le système d'héritage de Twig. Kesako ? en gros nous allons avoir une page parente qui va contenir des "block Twig" que nous pourrons réutiliser dans les pages enfants.
Nous allons créer un fichier base.html.twig dans le fichier src/T/MainBundle/Resources/views/base.html.twig voici son contenu :

<!DOCTYPE html>
<html>
<head>
<meta charset="UTF-8" />

<title>{% block title %}Mon super site{% endblock %}</title>

<meta name="title" content="{% block page_title %}Mon super site{% endblock %}"/>
<meta name="description" content="{% block meta_desc %}mon premier site avec Symfony 2{% endblock %}"/>

{% block stylesheet %}
<link rel="stylesheet" href="{{ asset('bundles/tmain/css/main.css') }}" />
{% endblock %}
<link rel="icon" type="image/x-icon" href="{{ asset('favicon.ico') }}" />
</head>
<body>
<div class="container-fluid">
{% block body %}
{% endblock %}
</div>
</body>
{% block javascripts %}
<script src="https://ajax.googleapis.com/ajax/libs/jquery/2.1.4/jquery.min.js"></script>
<script type="text/javascript" src="{{ asset('bundles/tmain/js/main.js') }}"></script>
{% endblock %}
</html>

Vous devez créer dans le répertoire src/T/MainBundle/Resources/public/css un fichier main.css
Idem pour le js src/T/MainBundle/Resources/public/js un fichier main.js

Ces deux fichiers sont nos feuilles de styles et js global. Maintenant que ces fichiers sont créer nous allons installer les assets.
Vous vous souvenez je vous ai dit que le répertoire web/ est le seul répertoire que les utilisateurs ont accès, et bien le problème c'est que vos feuilles de style / js / images / fonts sont stockés dans votre bundle.
Lorsque l'on installe les assets et bien cela veut dire que nous allons créer un répertoire dans le dossier web avec des liens symboliques vers notre répertoire public de notre bundle.
Au lieu d'un long discourt je vais vous montrez :

MBP-de-Yannick:tuto-blog yannick$ php app/console asset:install web --symlink
Trying to install assets as symbolic links.
Installing assets for Symfony\Bundle\FrameworkBundle into web/bundles/framework
The assets were installed using symbolic links.
Installing assets for T\MainBundle into web/bundles/tmain
The assets were installed using symbolic links.
Installing assets for Sensio\Bundle\DistributionBundle into web/bundles/sensiodistribution
The assets were installed using symbolic links.

Cette commande va donc créer des liens symboliques dans notre répertoire web/bundles/(ici les liens) vers notre répertoire public de notre bundle TMainBundle, si vous ne mettez pas l'option --symlink vous verrez que vous allez copier tous les dossiers / sous dossiers du répertoire public de votre bundle dans le dossier web/bundles/ le problème c'est que comme nous travaillons à l'intérieur de notre bundle à chaque modification des feuilles de style / js et bien nous serions obligé de réinstaller les assets ... ce n'est pas top.
Du coup en utilisant les liens symboliques nous n'avons plus ce problème.
Pour les utilisateurs windows il est possible de créer des liens symboliques que si votre terminal est lancer en administrateur.

Il existe une autre méthode pour les feuilles de style et js c'est de les créer et les mettre directement dans le répertoire web ( par exemple web/css/main.css) et dans notre code Twig avec une vhost de configurer nous pourrions appeler ce fichier en faisant "/" -> racine de notre serveur donc le dossier "web" "css/main.css" et voilà.
L'inconvénient c'est que le style css et le js n'est pas avec le bundle ( dans le répertoire public ), donc si demain ce bundle est amener à être récupérer pour un autre projet il va falloir vous embêtez à récupérer les feuilles de style et js qui sont planquer dans le dossier web, maintenant tout dépend de l'application que vous développez.

Une fois les assets installés vous pouvez accéder au répertoire web/bundles en utilisant une fonction Twig {{ asset('bundles/tmain/css/main.css') }} c'est pareil avec les images, par exemple {{ asset('bundles/tmain/images/monimage.jpg') }}

pour bien comprendre ce qui s'est passer après avoir installer les assets voici un petit screen de l'architecture mon dossier web :

Vous voyez la petite flèche sur le dossier "tmain" cela veut dire que c'est un lien symbolique (sur Phpstorm)

Apres avoir créer notre fichier base.html.twig nous allons maintenant créer un autre fichier qui sera l'enfant de base.html.twig c'est dans cet enfant que nous allons structurer nos pages.

Ps: Pour la structure que je suis en train de vous montrer ce n'est qu'à titre d'exemple, moi je préfère faire comme ça. Libre à vous de faire autrement. ayant travailler pendant 1 an en intégrateur sur Symfony j'ai mis en place une petite façon de faire que je trouve plutôt propre pour moi :)

Voici donc le fichier layout.html.twig qui sera dans le répertoire src/T/MainBundle/Resources/views/layout.html.twig :

{% extends 'TMainBundle::base.html.twig' %}

{% block body %}

{% block header %}
<div class="row">
<div class="col-md-12">
Header
</div>
</div>
{% endblock %}

{% block content %}
{% endblock %}

{% block footer %}
<div class="row ">
<div class="col-md-12 ">
Footer
</div>
</div>
{% endblock %}

{% endblock %}

Nous allons modifier nos deux templates de tout à l'heure. index.html.twig et tarif.html.twig

{% extends 'TMainBundle::layout.html.twig' %}

{% block content %}
<div class="row">
<div class="col-md-12">
<p>Ici le contenu de la page index</p>
</div>
</div>
{% endblock %}
{% extends 'TMainBundle::layout.html.twig' %}

{% block content %}
<div class="row">
<div class="col-md-12">
<p>Ici le contenu de la page tarif</p>
</div>
</div>
{% endblock %}

 

Et voilà nos deux pages extend du layout qui lui même extend du base.html.twig nous allons donc pouvoir hériter des blocks des deux parents, par exemple nous pouvons changer le title de la page sur nos deux page :

{% extends 'TMainBundle::layout.html.twig' %}

{% block title %}
{#je recupere le contenu du block parent#}
{{ parent() }} - Tarif
{% endblock %}

{% block content %}
<div class="row">
<div class="col-md-12">
<p>Ici le contenu de la page tarif</p>
</div>
</div>
{% endblock %}

 

Vous l'aurez remarquer j'utilise les class de bootstrap mais je ne l'ai pas encore implémenter, je l'ajoute un peu plus bas dans le tuto ;)


Voici ce que ça donne avec notre nouvelle structure lorsque je veux afficher la page tarif :

Installer bootstrap

Avant de terminer cette première partie du tuto je vais installer avec vous bootstrap :) donc direction le site de bootstrap pour récupérer le zip. Une fois récupérer vous pouvez directement le deziper dans votre répertoire public (src/T/MainBundle/Resources/public/...) récupérer surtout les dossiers css/js/fonts qui sont dans le zip et fusionner les avec ceux du répertoire public.
Une fois que c'est fait voyons voir ce que l'on a là dedans :)
our notre tuto nous allons avoir besoin que de min.css et min.js ainsi que les fonts on peut le supprimer :

 

Nous allons donc ajouter tout ça dans notre base.html.twig et c'est fini !

<!DOCTYPE html>
<html>
<head>
<meta charset="UTF-8" />

<title>{% block title %}Mon super site{% endblock %}</title>

<meta name="title" content="{% block page_title %}Mon super site{% endblock %}"/>
<meta name="description" content="{% block meta_desc %}mon premier site avec Symfony 2{% endblock %}"/>

{% block stylesheet %}
<link rel="stylesheet" href="{{ asset('bundles/tmain/css/bootstrap.min.css') }}" />
<link rel="stylesheet" href="{{ asset('bundles/tmain/css/main.css') }}" />
{% endblock %}
<link rel="icon" type="image/x-icon" href="{{ asset('favicon.ico') }}" />
</head>
<body>
<div class="container-fluid">
{% block body %}
{% endblock %}
</div>
</body>
{% block javascripts %}
<script src="https://ajax.googleapis.com/ajax/libs/jquery/2.1.4/jquery.min.js"></script>
<script type="text/javascript" src="{{ asset('bundles/tmain/js/bootstrap.min.js') }}"></script>
<script type="text/javascript" src="{{ asset('bundles/tmain/js/main.js') }}"></script>
{% endblock %}
</html>

 

Voilà cette première partie de mon premier tuto sur viking lab se termine j'espère que ça vous a plus.
Si vous avez des questions n'hésitez pas à m'envoyer un mail ou bien laisser un commentaire.

Pour récupérer le code du projet c'est ici => https://github.com/vikinglab/tuto-blog

Attention je vais le mettre à jour avec la partie 2 et 3 donc il risque d'évoluer ! De plus vous n'aurais pas les vendor (c'est ici que se cache les bundles) donc il faudra faire :

php composer.phar install

 Comme je suis super sympa je vous ai mis dans le repository le fichier composer.phar comme ça vous n'avez qu'à le lancer ;)

Créer une page contact avec Symfony 2