Présentation de Silex


Silex est un micro-framework pour PHP 5.3 basé sur les briques de Symfony 2 et de Pimple. Ce framework a été créé dans l'objectif de proposer un système simple permettant de réaliser des applications simples sans avoir à utiliser un framework complexe.
Silex a été créé par Fabien Potencier et Igor Wiedler.

Le projet : Jeudi croissants


Nous allons réaliser un projet que vous devriez aimer (ou pas).
Tous les jeudis, nous avons la coutume suivante : une personne désignée doit ramener les croissants et les pains au chocolat pour tout le monde.
Cette personne change bien évidemment chaque semaine.
Nous allons donc réaliser une application se composant de 3 pages:
 - d'un front permettant de voir qui est la prochaine personne qui doit ramener les croissants
 - d'une page permettant d'augmenter la participation d'un membre
 - d'une page permettant de réduire la participation d'un membre

Cette application n'a pas pour objectif d'être un monstre en matière de sécurité. Il n y aura pas de gestion d'utilisateurs avec des permissions.
Cette coutume est bien évidemment ancrée sous le nom de jeudi croissants (donc pas de Tuesday crescent ou autres ...).

Mise en place du projet et installation de Silex


Commencons par configurer un vhost très simple :


NameVirtualHost *:80
<VirtualHost *:80>
ServerAdmin webmaster@localhost
ServerName jeudi.local
ServerAlias jeudi.local
DocumentRoot /var/www/jeudi/
DirectoryIndex index.php
<Directory /var/www/jeudi>
Options Indexes FollowSymLinks MultiViews
#AllowOverride None
Order allow,deny
allow from all
</Directory>
</VirtualHost>


N'oubliez pas de renseigner jeudi.local dans votre fichier /etc/hosts, d'activer le vhost et de recharger la conf apache.

Pour l'installation de Silex c'est très facile. Il suffit de récupérer le phar et c'est terminé !

cd /var/www/
mkdir jeudi
cd jeudi
wget "http://silex-project.org/get/silex.phar"

Nous aurons besoin du moteur de template Twig pour ce projet.
Twig n'étant pas inclus dans le phar, vous devrez donc le télécharger vous même. Copiez le dans /var/www/jeudi/vendor/twig

Concernant le stockage des données, nous allons utiliser un simple fichier texte data.txt.

cd /var/www/jeudi
mkdir data
touch data/data.txt

Voici un jeu de fixtures pour votre fichier :

gbretou:5
atisset:3
mwolff:3


Assurez vous que le fichier est accessible en écriture.
NB. Il est possible d'utiliser Doctrine 2 avec Silex. Il existe en effet une extension. Cela fera l'objet soit d'une mise à jour de cet article, soit d'un prochain article.

Le code de l'application


On commence donc avec un fichier index.php très basique :

//index.php

<?php
require_once __DIR__.'/silex.phar';
$app = new Silex\Application();
// definitions
$app->run();


Nous allons devoir ajouter un service pour gérer les intéractions avec le fichier. Nous allons donc créer la classe ParticipationService.
Ce service devra être enregistré dans l'application Silex.


//index.php
require_once __DIR__.'/ParticipationService.php';
//...
$app['participation'] = $app->share(function () {
    return new ParticipationService('./data/data.txt');
});

Vous trouverez la classe ParticipationService dans l'archive en pièce jointe.

Afin de pouvoir utiliser Twig, il faudra enregistrer l'extension :

$app->register(new Silex\Extension\TwigExtension(), array(
    'twig.path'       => __DIR__.'/views',
    'twig.class_path' => __DIR__.'/vendor/twig/lib',
));


twig.path doit pointer sur votre dossier contenant les fichiers templates.
twig.class_path doit pointer sur le dossier contenant les classes de Twig.

Nous avons défini que l'application devait se composer de 3 routes :
 - une route pour la visualisation
 - une route pour l'incrémentation
 - une route pour la décrémentation

La visualisation


Nous allons définir la route suivante :

//index.php
$app->get('/', function () use ($app) {
    return $app['twig']->render('index.twig', array(
        'name'           => 'admin',
        'participations' => $app['participation']->getParticipations(),
        'next'           => $app['participation']->getNext(),
        'matrix'         => $app['participation']->getParticipationMatrix(),
    ));
});


Avec ce code, lors de l'accès à la homepage du site, le système traitera le template index.twig dans lequel on injecte plusieurs variables : name, participations, next et matrix. Ces variables sont récupérées par le service ParticipationService.

L'incrémentation et la décrémentation


Voici les routes pour l'incrémentation et la décrémentation :

//index.php
$app->get('/increase/{name}/{count}', function ($name, $count) use ($app) {
    try
    {
        $app['participation']->increaseParticipation($name, $count);
        return $app['twig']->render('update.twig', array(
            'name' => $name,
        ));
    }
    catch (Exception $e)
    {
        return $app['twig']->render('error.twig', array(
            'exception' => $e->getMessage(),
        ));
    }
});

$app->get('/decrease/{name}/{count}', function ($name, $count) use ($app) {
    try
    {
        $app['participation']->decreaseParticipation($name, $count);
        return $app['twig']->render('update.twig', array(
            'name' => $name,
        ));
    }
    catch (Exception $e)
    {
        return $app['twig']->render('error.twig', array(
            'exception' => $e->getMessage(),
        ));
    }
});


Chaque route se compose de parties variables encadrées par des {}. Ces variables sont ensuite récupérées et transférées à la closure manuellement.
Afin d'avoir une application RESTFUL, on pourrait utiliser un put plutôt qu'un get pour les modifications.

Pour vous aider dans vos développements, pensez à activer le mode debug :

$app['debug'] = true;



Edit du 17/06/2011
:
Il est possible de catcher les exceptions mieux que je ne l'ai fait : voir la partie sur les error handlers. Je mettrai le code à jour.

Conclusion


Vous trouverez une archive contenant l'application. N'hésitez pas à me faire part de vos remarques.

J'ai aimé

 - La rapidité et la simplicité : on a une application avec un feedback visuel en quelques secondes
 - La documentation : pour mon utilisation, j'ai trouvé la documentation claire

Je n'ai pas aimé (?)

J'aurais souhaité utiliser des tâches pour mettre à jour les informations de participation. Cependant, d'après ce que j'ai constaté, Silex fournit une console qui ne prend en paramètre que 3 valeurs possibles : check, update et version. Je ne sais pas s'il est possible d'étendre ce système pour définir des tâches personnalisées dans le framework.


Comme l'a souligné scrumasteriswatchingu, si vous avez installé suhosin, vous devez ajouter la directive suivante dans votre php.ini
suhosin.executor.include.whitelist = phar


PS : La coutume Jeudi Croissant a été inventé mwolff ;p

L'application Jeudi croissant est disponible sur bitbucket : https://bitbucket.org/guiguiboy/jeudi-croissant

Edit du 16/03/2012
Le projet a été mis à jour pour utiliser la dernière version de Silex