XXVIII. 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 :
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) :
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 paquetage, comme nous l'avons vu dans un chapitre précédentchapitre précédent précédentChapitre 26 : Création d'un paquetage. 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.
XXVIII-A. Générer la classe▲
La première chose consiste à générer la classe avec Artisan. La syntaxe est simple :
Le nom de la classe doit comporter le suffixe Command. Voici le code généré :
2.
3.
4.
5.
6.
7.
8.
9.
10.
11.
12.
13.
14.
15.
16.
17.
18.
19.
20.
21.
22.
23.
24.
25.
26.
27.
28.
29.
30.
31.
32.
33.
34.
35.
36.
37.
38.
39.
40.
41.
42.
43.
44.
45.
46.
47.
48.
49.
50.
51.
52.
53.
54.
55.
56.
57.
58.
59.
60.
61.
62.
63.
64.
65.
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 :
On va commencer par renseigner le nom de la commande ainsi que sa description :
On vérifie que la commande est bien prise en compte avec php artisan list :
XXVIII-A-1. 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 :
Puisqu'on veut reproduire cette commande et la compléter, il faut prévoir son argument et ses options :
2.
3.
4.
5.
6.
7.
8.
9.
10.
11.
12.
13.
14.
15.
16.
17.
18.
19.
20.
21.
22.
23.
/**
* 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 :
XXVIII-A-2. 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 ) :
2.
3.
4.
5.
6.
7.
8.
9.
10.
11.
12.
13.
14.
15.
16.
17.
18.
19.
20.
21.
22.
23.
24.
25.
26.
27.
28.
29.
30.
31.
32.
33.
34.
35.
36.
37.
38.
39.
40.
41.
42.
43.
44.
45.
46.
47.
48.
49.
50.
51.
52.
53.
54.
55.
56.
57.
58.
59.
60.
61.
62.
63.
64.
65.
66.
67.
68.
69.
70.
71.
72.
73.
74.
75.
76.
77.
78.
79.
80.
81.
82.
83.
84.
85.
86.
87.
88.
89.
90.
91.
92.
93.
94.
95.
96.
97.
98.
99.
100.
101.
102.
103.
104.
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 :
2.
3.
4.
5.
6.
7.
8.
9.
10.
11.
12.
13.
14.
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 :
On vérifie l'écriture des valeurs dans le fichier app/config/workbench.php :
2.
3.
4.
5.
6.
7.
8.
9.
10.
11.
12.
13.
14.
15.
16.
17.
18.
19.
20.
21.
22.
23.
24.
25.
26.
27.
28.
29.
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 :
On supprime ce dossier et on teste avec l'option -resources :
Résultat :