Laravel 4

Laravel 4 : chapitre 28 : Créer une commande

Nous avons vu plusieurs fois l’utilisation d’artisan au cours des précédents articles, que ce soit pour créer un contrôleur, remplir une base, générer l’autoload, créer un workbench… Pour connaître toutes les commandes disponibles il suffit de taper dans la console php artisan list :

img59

Et pour obtenir le détail d’une commande particulière on utilise la syntaxe php artisan help commande (ou la syntaxe courte php artisan commande -h) :

img60

Mais il se peut que l’on ait besoin d’une commande non prévue, un truc à notre sauce. Laravel nous permet de composer une commande personnalisée facilement, c’est ce que nous allons voir avec un exemple.

Il existe la commande command:make pour créer un package, comme nous l’avons vu dans un article précédent. Mais il y a un truc un peu agaçant, il faut au préalable renseigner le fichier app/config/workbench avec le nom et l’email. On va créer une commande qui permet de renseigner ces deux valeurs et ensuite lancer la commande de base.

Vous avez la documentation correspondante ici. Je n’ai pas détaillé toutes les possibilités, reportez-vous à cette page pour les détails…

Générer la classe

La première chose consiste à générer la classe avec artisan. La syntaxe est simple :

img64

Le nom de la classe doit comporter le suffixe Command. Voici le code généré :

use Illuminate\Console\Command;
use Symfony\Component\Console\Input\InputOption;
use Symfony\Component\Console\Input\InputArgument;

class WorkbenchPlusCommand extends Command {

	/**
	 * The console command name.
	 *
	 * @var string
	 */
	protected $name = 'command:name';

	/**
	 * The console command description.
	 *
	 * @var string
	 */
	protected $description = 'Command description.';

	/**
	 * Create a new command instance.
	 *
	 * @return void
	 */
	public function __construct()
	{
		parent::__construct();
	}

	/**
	 * Execute the console command.
	 *
	 * @return void
	 */
	public function fire()
	{
		//
	}

	/**
	 * Get the console command arguments.
	 *
	 * @return array
	 */
	protected function getArguments()
	{
		return array(
			array('example', InputArgument::REQUIRED, 'An example argument.'),
		);
	}

	/**
	 * Get the console command options.
	 *
	 * @return array
	 */
	protected function getOptions()
	{
		return array(
			array('example', null, InputOption::VALUE_OPTIONAL, 'An example option.', null),
		);
	}

}

Et on enregistre notre commande dans le fichier app/start/artisan.php :

Artisan::add(new WorkbenchPlusCommand);

On va commencer par renseigner le nom de la commande ainsi que sa description :

	/**
	 * The console command name.
	 *
	 * @var string
	 */
	protected $name = 'workbenchplus';

	/**
	 * The console command description.
	 *
	 * @var string
	 */
	protected $description = 'Create a new package workbench with name and email.';

On vérifie que la commande est bien prise en compte avec php artisan list :

 img65

Argument et options

Une commande peut avoir un argument et des options. C’est le cas de la commande workbench. On peut le vérifier :

img66

Puisqu’on veut reproduire cette commande et la compléter il faut prévoir son argument et ses options :

	/**
	 * Get the console command arguments.
	 *
	 * @return array
	 */
	protected function getArguments()
	{
		return array(
			array('package', InputArgument::REQUIRED, 'The name (vendor/name) of the package.'),
		);
	}

	/**
	 * Get the console command options.
	 *
	 * @return array
	 */
	protected function getOptions()
	{
		return array(
			array('resources', null, InputOption::VALUE_NONE, 'Create Laravel specific directories.'),
		);
	}

On vérifie :

img67

Codage de la commande

Il ne nous reste plus qu’à coder la commande. Il nous faut :

  • lire le fichier app/config/workbench.php
  • interroger l’utilisateur pour avoir les valeurs pour le nom et l’email
  • modifier le fichier app/config/workbench.php en conséquence
  • lancer la commande workbench

Laravel offre la classe Illuminate\Filesystem\Filesystem pour faciliter les manipulations de fichiers. Nous allons donc utiliser cette classe. Voici le code complet de la commande (comme les commentaires de base étaient en anglais j’ai continué dans ce langage Undecided):

use Illuminate\Console\Command;
use Symfony\Component\Console\Input\InputOption;
use Symfony\Component\Console\Input\InputArgument;

class WorkbenchPlusCommand extends Command {

    /**
     * The console command name.
     *
     * @var string
     */
    protected $name = 'workbenchplus';

    /**
     * The console command description.
     *
     * @var string
     */
    protected $description = 'Create a new package workbench.';

    /**
     * The file system instance.
     *
     * @var string
     */
    protected $files;

    /**
     * Set configuration item
     *
     * @param  string $contents
     * @param  string $key
     * @param  string $value
     * @return void
     */
    private function setItem(&$contents, $key, $value)
    {
        $pattern = "#('$key' => ').*'#";
        $replacement = "$1$value'";
        $contents = preg_replace($pattern, $replacement, $contents);
    }
    /**
     * Create a new command instance.
     *
     * @param  \Illuminate\Filesystem\Filesystem  $files
     * @return void
     */
    public function __construct(Filesystem $files)
    {
        parent::__construct();
        $this->files = $files;
    }

    /**
     * Execute the console command.
     *
     * @return void
     */
    public function fire()
    {
        // Name
        $name = $this->ask("What is the name ?");
        // Email
        $email = $this->ask("What is the email ?");
        // Workbench config file content
        $contents = $this->files->get($path = $this->laravel['path'].'/config/workbench.php');    
        // Set name
        $this->setItem($contents, 'name', $name);
        // Set email
        $this->setItem($contents, 'email', $email);
        // Save config file
        $this->files->put($path, $contents);
        // Call workbench command
        $this->call('workbench', array(
            'package' => $this->argument('package'), 
            '--resources' => $this->option('resources') 
        ));
    }

    /**
     * Get the console command arguments.
     *
     * @return array
     */
    protected function getArguments()
    {
        return array(
            array('package', InputArgument::REQUIRED, 'The name (vendor/name) of the package.'),
        );
    }

    /**
     * Get the console command options.
     *
     * @return array
     */
    protected function getOptions()
    {
        return array(
            array('resources', null, InputOption::VALUE_OPTIONAL, 'Create Laravel specific directories.', null),
        );
    }

}

Vous remarquez que j’ai prévu l’injection d’une instance de la classe Filesystem plutôt que de l’utiliser directement dans le code. C’est une approche orientée sur la testabilité du code. Mais du coup il faut compléter l’appel de la commande dans le fichier app/start/artisan.php :

use Illuminate\Filesystem\Filesystem;

/*
|--------------------------------------------------------------------------
| Register The Artisan Commands
|--------------------------------------------------------------------------
|
| Each available Artisan command must be registered with the console so
| that it is available to be called. We'll register every command so
| the console gets access to each of the command object instances.
|
*/

Artisan::add(new WorkbenchPlusCommand(new Filesystem));

Et son test :

img68

On vérifie l’écriture des valeurs dans le fichier app/config/workbench.php :

return array(

	/*
	|--------------------------------------------------------------------------
	| Workbench Author Name
	|--------------------------------------------------------------------------
	|
	| When you create new packages via the Artisan "workbench" command your
	| name is needed to generate the composer.json file for your package.
	| You may specify it now so it is used for all of your workbenches.
	|
	*/

	'name' => 'bestmomo',

	/*
	|--------------------------------------------------------------------------
	| Workbench Author E-Mail Address
	|--------------------------------------------------------------------------
	|
	| Like the option above, your e-mail address is used when generating new
	| workbench packages. The e-mail is placed in your composer.json file
	| automatically after the package is created by the workbench tool.
	|
	*/

	'email' => 'bestmomo@chez.moi',

);

Et la création du workbench :

img71

On supprime ce dossier et on teste avec l’option –resources :

img70

Résultat :

img71jpg

Print Friendly, PDF & Email

Laisser un commentaire