Bootstrap CLI
By Geoffrey on Friday 13 October 2006, 18:31 - Coding - Permalink
Tags :
Nous avons parcouru dernièrement la création du bootstrap HTTP qui sert de socle à une application utilisant le Zend Framework. Le même principe peut s'appliquer aux scripts CLI, mais comme les besoins sont fondamentalements différents, l'implémentation sera elle aussi complètement différente. Nous viserons les objectifs suivants:
- Ne pas être obligé d'executer le bootstrap en ligne de commande
- Simplifier au maximum l'écriture ultérieure des scripts CLI
- Définir un jeu d'options de ligne de commande obligatoire
- Mettre en place un environnement d'execution
La tentation serait de créer un système qui obligerait ce genre de commandes:
$ php batch/bootstrap.php monscript
Pour executer, par exemple, le script batch/monscript.php. Cela simplifierait grandement les choses, mais c'est moche, et puis on peut faire autrement, donc on ne va pas se priver ! Nous utiliserons a cette fin la fonction magique register_shutdown_function, qui s'occupera d'appeler une fonction qui executera les scripts ad hoc.
Avant d'aller plus loin, l'arborescence de fichiers que nous allons utiliser:
batch/ monscript.php runtime.php library/ Zend.php My/ Batch.php
runtime.php sera le fichier à inclure dans chaque script, tandis que My/Batch.php contiendra la classe d'abstraction My_Batch, qui définira les comportements par défaut de nos scripts.
Voici donc la première partie de notre bootstrap, batch/runtime.php:
ini_set('include_path', get_include_path().PATH_SEPARATOR.realpath(dirname(__FILE__).'/../library/'));
require_once 'Zend.php';
require_once 'My/Batch.php';
register_shutdown_function(array('My_Batch', 'runAll'));
Bien sur, cette méthode nous oblige à définir un format à respecter pour les fonctions à executer par la suite, nous partirons donc sur les bases suivantes:
- Chaque batch doit être constitué d'une classe dont le nom commence par
My_Batch_ - Chaque batch doit posséder une méthode executable
run
Ce qui nous donne donc:
abstract class My_Batch {
static public function runAll() {
$classes = get_declared_classes();
foreach($classes as $className) {
if (preg_match('/^My_Batch_(.+)$/', $className, $matches) && method_exists($className, 'run')) {
try {
$batch = new $className;
$batch->run();
} catch (Exception $e) {
die(sprintf("%s: %s\n", $matches[1], $e->getMessage()));
}
}
}
}
abstract public function run();
}
On en profite pour catcher toute Exception indésirable pour la transformer en un die, bien plus lisible dans un terminal qu'une backtrace :-)
Maintenant que nous avons résolu les points 1 et 2, attaquons nous à la suite. Le problème principal que j'ai rencontré lors de l'établissement d'un environnement d'execution, c'est que la gestion de la configuration repose en grande partie sur la valeur de $_SERVER['HTTP_HOST'], qui n'est bien évidemment pas disponible en CLI :-) Il me faut donc forcer le passage en argument du nom de la configuration à utiliser. C'est très simple à faire, grace a la méthode que nous avons employé: il suffit de vérifier la présence de cet argument dans le constructeur de My_Batch :-)
public function __construct() {
foreach($GLOBALS['argv'] as $i => $arg) {
switch ($arg) {
case '--configname':
case '-c':
$this->_args['configname'] = $GLOBALS['argv'][$i+1];
break;
}
}
if (!isset($this->_args['configname'])) {
throw new Exception('-c or --configname is mandatory');
}
}
Voilà, le gros du travail est fait. Pour le reste, c'est la routine, mise en place d'un environnement avec Zend_Config et Zend_Db, a la suite dans le constructeur:
$this->_config = new Zend_Config( Zend_Config_Ini::load( dirname(__FILE__).'/../../app/config.ini', $this->_args['configname'] ) ); $this->_db = Zend_Db::factory( $this->_config->db->adapter, $this->_config->db->config->asArray() ); Zend_Db_Table::setDefaultAdapter($this->_db);
Enfin, voila un exemple de script utilisant ce bootstrap:
require_once 'path/to/runtime.php';
class My_Batch_MonScript extends My_Batch {
public function run() {
// le code ici
}
}
And voila !
no comment
This post's comments feed