PHP: Projet Silex - Configuration de Silex

L'introduction de cet article est PHP: Projet Silex – Présentation, pré-requis et architecture. Je vous invite à le lire si vous prenez le train en route.
En attendant, un petit rappel de notre avancement :

Road map du projet

  1. Pré-requis et architecture
  2. Configuration de Silex
  3. Jouons avec Silex
  4. Ecriture de tests fonctionnels
  5. TDD pour le code métier
  6. Templating

La dernière fois, nous avons préparé l'environnement de notre projet en configurant Apache et PHP puis en téléchargeant Silex, Twig et Monolog. Aujourd'hui, nous allons entrer un peu plus dans le vif du sujet puisqu'on va configurer Silex et faire un bon vieux Hello world! mais pas que, on va tester Twig et Monolog pour faire d'une pierre deux coups.

2. Configuration de Silex

Avant toute chose, vous devez savoir que Silex a un développement très actif au moment où j'écris l'article donc la première chose à faire est de savoir si vous avez la dernière version :

php silex.phar check
You are using the latest Silex version.

Si ça n'est pas le cas, mettez-le à jour et prenez l'habitude de le faire à chaque fois que vous l'utilisez :

php silex.phar update

Création des fichiers

Au début, rien de bien compliqué puisqu'en lisant la doc, je suis complètement dispensable (sauf peut-être pour les réticents à l'anglais et j'en connais) mais ça va dans la continuité du projet alors on y va.
On commence par créer les fichiers utiles :

touch src/portfolio.php log/portfolio.log web/index.php src/views/layout.twig src/views/index.twig

Hello world!

Munissez-vous de votre éditeur favoris et on y va :

<?php
// portfolio.php
require_once __DIR__ . '/../vendor/Silex/silex.phar';
 
$app = new Silex\Application();
$app->get('/', function() {
    return 'Hello world!';
});
 
return $app;
<?php
// index.php
$portfolio = require_once __DIR__ . '/../src/portfolio.php';
$portfolio->run();
?>

Ok, c'est méga simple et après avoir lancé votre serveur HTTP, on regarde le résultat sur https://local.dev.photo.eexit. Si vous n'avez pas d'erreur, vous êtes sur la bonne voie.

Configuration de Monolog

Très simplement, on va mettre en place le super logger Monolog pour notre méga application. Comme dans la doc de Silex, on y a pas à pas pour greffer l'extension (si possible avant les déclarations de route) :

<?php
// portfolio.php
 
// Instantiation de Silex
 
$app->register(new Silex\Extension\MonologExtension(), array(
    'monolog.class_path'    => __DIR__ . '/../vendor/monolog/src',
    'monolog.logfile'       => __DIR__ . '/../log/portfolio.log',
    'monolog.name'          => 'portfolio',
    'monolog.level'         => 300 // = Logger::WARNING
));
 
// Routes

Si vous retournez sur https://local.dev.photo.eexit, rien ne s'inscrit dans le log car on se fiche bien d'un simple GET, par contre, si vous allez sur https://local.dev.photo.eexit/foo, alors une 404 sera remontée et logguée (et un beau pâté d'erreur PHP aussi).
Intéressant !

[2011-05-16 13:15:45] portfolio.WARNING: 404 GET /foo

Gestion des erreurs

Tant qu'à faire, pourquoi ne pas gérer immédiatement les erreurs avec Silex puisqu'il existe une méthode prévue à cet effet. Ce sera toujours mieux d'afficher une belle page plutôt qu'une trace d'exception ou une page blanche.
Pour cela, nous allons ajouter quelques importations de namespaces avant l'inclusion de Silex et nous allons déclarer le comportement que Silex doit adopter quand il rencontre une erreur :

<?php
// portfolio.php
use Symfony\Component\HttpFoundation\Response;
use Symfony\Component\HttpKernel\Exception\HttpException;
use Symfony\Component\HttpKernel\Exception\NotFoundHttpException;
 
require_once __DIR__ . '/../vendor/Silex/silex.phar';
 
// Instantiation de Silex + Monolog
 
$app->error(function(\Exception $e) use ($app) {
    if ($e instanceof NotFoundHttpException) {
        $content = vsprintf('<h1>%d - %s (%s)</h1>', array(
           $e->getStatusCode(),
           Response::$statusTexts[$e->getStatusCode()],
           $app['request']->getRequestUri()
        ));
        return new Response($content, $e->getStatusCode());
    }
 
    if ($e instanceof HttpException) {
        return new Response('<h1>You should go eat some cookies while we\'re fixing this feature!</h1>', $e->getStatusCode());
    }
});
 
// Routes

On actualise et là nous avons un beau message d'erreur un peu plus compréhensible pour l'utilisateur :

Il est clair que vous pouvez agrémentez autant que possible votre closure afin d'envoyer un email par exemple... Les possibilités sont infinies à ce niveau-là.

Configuration de Twig

De la même manière que pour Monolog, on va greffer Twig à notre application :

<?php
// portfolio.php
 
// Instantiation de Silex + Monolog
 
$app->register(new Silex\Extension\TwigExtension(), array(
   'twig.class_path'    => __DIR__ . '/../vendor/Twig/lib',
   'twig.path'          => __DIR__ . '/views'
));
 
// Gestion erreur + routes

Maintenant nous allons éditer les fichiers .twig afin de templater un minimum notre rendu HTML :

{# layout.twig #}
<!doctype html>
<html lang="en">
    <head>
        <title>Portfolio</title>
        <meta http-equiv="Content-Type" content="text/html;charset=utf-8">
    </head>
    <body>
        {% block body %}{% endblock %}
    </body>
</html>
{# index.twig #}
{% extends 'layout.twig' %}
{% block body %}
<p>{{ hello }}</p>
{% endblock %}

Donc de manière très simple, on a le fichier index.twig qui sera inclu dans layout.twig et renvoyé au front controller. Nous avons déclaré une variable hello dans index.twig qui sera remplacée par la valeur que nous allons lui assigner dans la closure de notre route :

<?php
// portfolio.php
 
$app->get('/', function() use ($app) {
    return $app['twig']->render('index.twig', array(
        'hello' => 'Hello world!'
    ));
});

Note : Silex hérite de Pimple qui lui-même implémente l'interface ArrayAccess. Cela permet d'accéder aux membres de Silex sans fait appel à des getters.

Rien de plus et en allant sur notre index, on obtient le résultat suivant :

N'ayant encore jamais utilisé Twig, je découvre donc on ira pas à pas dans la partie destinée au templating du projet. En tout cas, c'est vraiment très agréable d'avoir un code propre...

Ce sera tout pour cet article, aujourd'hui, nous avons vu comment préparer notre micro-framework pour commencer le développement de notre projet. Nous verrons la prochaine fois comment tirer un maximum des outils proposé par Silex tout en utilisant la tout puissance des closures PHP !
N'oubliez pas de me suivre sur Twitter.

Aller à l'étape suivante ›

‹ Aller à l'étape précédente