Utilisation de la console avec Symfony 2


Technique

Lors du développement et de la maintenance d’une application pour le web, il arrive souvent de devoir lancer des process parallèles au fonctionnement normal du projet. Leur but peut par exemple être de gérer des fixtures pour remplir la base de données ou encore d’exporter des données en csv. Il faut alors se poser la question de la technique à utiliser pour créer ces outils. Une des réponses à ce besoin est l’utilisation de la console, qui apporte plusieurs avantages par rapport aux actions habituelles lancées à partir du navigateur :

  • Tout d’abord, le développeur n’a pas besoin de prendre le temps de coder une interface web et celui-ci reste dans son environnement habituel.
  • D’autre part, PHP en mode console a accès à davantage de ressources.

Le framework Symfony 2 est livré avec un composant Console qui simplifie la gestion des entrées et des sorties du process. Nous allons l’utiliser pour créer un outil simple en ligne de commande qui permet d’afficher le hash d’une chaîne de caractères, avec le choix de la méthode de hashage.

A partir du répertoire app/ de votre installation de Symfony 2, lancez la commande suivante pour générer le bundle :

php console generate:bundle --namespace="Disko/HashBundle" --format="yml" --dir="../src" --structure=true -–no-interaction

Les bundles sont à Symfony ce que les modules sont à Drupal : des plugins dépendants qui peuvent contenir du code métier, des vues, des images, du code javascript… Symfony 2 est entièrement construit sur des Bundles, il est d’ailleurs possible d’en télécharger un certain nombre sur symfony2bundles.

Il faut ensuite créer une classe HashCommand un répertoire Command/ du bundle récemment créé. Cette classe va étendre ContainerAwareCommand qui permet à la fois d’utiliser le système d’injection de dépendance de Symfony, et d’utiliser les différentes fonctions de passage d’arguments ou de colorisation propre à une application shell.

Voici la structure minimale d’une classe destinée à la console telle que nous allons l’utiliser dans notre script :
setName('disko:hash')
->setDescription('Hash une chaîne de caractère');
}

protected function execute(InputInterface $input, OutputInterface $output)
{
}
}

Notre commande va donc avoir besoin de deux entrées : la chaîne de caractères à hasher qui sera obligatoire et éventuellement une ou plusieurs méthodes de hashage (si aucune méthode de hashage n’est donnée, on utilisera toutes celles qui sont disponibles).
Pour faire passer des entrées, il est possible d’utiliser soit les arguments soit les options. La différenciation se fait dans la façon dont les paramètres sont passés : les arguments ne sont pas nommés et leur ordre est important, tandis que les options sont quant à elles nommées.

Pour ajouter des arguments à la commande, il suffit d’appeler addArgument dans la méthode de configuration :

$this->addArgument('str', InputArgument::REQUIRED, "La chaîne de caractère à hasher");
$this->addArgument('algo', InputArgument::IS_ARRAY, "Le ou les algorithmes de hashage à utiliser");

Finalement, le métier de l’application se code dans la méthode execute(). Comme pour les actions utilisées habituellement dans un contrôleur Symfony2, l’entrée (c’est à dire l’objet de requête) et la sortie (la réponse) sont passées directement à la méthode. Les valeurs des arguments seront donc récupérées via l’objet de requête, et l’écriture dans la console se fera en passant par l’objet de réponse :


protected function execute(InputInterface $input, OutputInterface $output)
{
$str = $input->getArgument('str');
$algos = $input->getArgument('algo');

/**
* hash_algos() liste tous les algorithmes disponibles
* dans le build actuel de PHP
*/
$available = hash_algos();
if( empty($algos) ) {
$algos = $available;
}

$output->writeln("{$str}");

foreach( $algos as $algo ) {
/**
* si l'algorithme demandé n'existe pas, on affiche
* un message d'erreur, sinon le résultat
*/
if( !in_array($algo, $available) ) {
$output->writeln("L'algorithme de hashage {$algo} n'est pas disponible.");
} else {
$output->writeln("{$algo}t" . hash($algo, $str) );
}
}
}

Remarquez la présence des balises qui vont coloriser le texte pour faciliter la lecture de la sortie. Et voilà le résultat !

console 640x105 Utilisation de la console avec Symfony 2

Au final, grâce au composant console de Symfony2, nous avons pu créer un outil pratique et flexible à utiliser via le shell. Néanmoins la création de process en ligne de commande est encore peu répandue chez les développeurs web et reste à tort un outil d’administrateur système.
Espérons que cela change, car le confort et la souplesse de ce type de script -surtout par rapport aux développements web classiques- présente bon nombre d’avantages bien souvent sous-exploités.

Le pôle technique

Laisser un commentaire

  1. Pas mal du tout. Il faut dire qu’en développement système après les PERL, PYTHON, et autre bash-lyke, les process PHP viennent compléter un arsenal déjà long. Mais c’est intéressant rien que pour l’interaction avec des appli web existantes ! Chapeau à l’équipe, je vois que vous assumez votre coté geek multi-techno :)