XXVI. Chapitre 26 : Création d'un paquetage▲
Pour ajouter des fonctionnalités à Laravel le plus simple est de créer un paquetage. D'ailleurs Laravel est lui-même un paquetage. Vous trouverez tous les paquetage utilisables avec composer sur le site Packagist. Par exemple on trouve Laravel ici sur ce site. Certains des paquetages sont destinés spécifiquement à Laravel 4, la plupart ne le sont pas spécialement mais peuvent évidemment tout de même être utilisés avec Laravel.
Dans Laravel 3 on ajoutait des bundles, pour Laravel 4 c'est donc différent, il faut créer des paquetages qui sont reconnus valides par composer. Je vous propose un exemple simple. Laravel possède une classe Form qui permet de créer facilement des formulaires, nous l'avons déjà vue et utilisée. Nous allons considérer que nous désirons les nouvelles possibilités du HTML5 au niveau des balises <input> avec les types color, date, etc. En effet la classe Form ne nous propose que le type email parmi ces nouvelles possibilités (mon exemple est un peu artificiel parce qu'on peut utiliser la méthode input de Form pour obtenir tous les types, mais comme ça on ne va pas se perdre dans le code du paquetage qui va rester élémentaire).
Commencez par créer une nouvelle installation de Laravel 4. Vous devez obtenir cette arborescence :
XXVI-A. Le workbench▲
Laravel nous offre un outil pratique pour créer un paquetage: le workbench (plan de travail). Mais il va nous falloir d'abord renseigner deux éléments (nom et adresse email) 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.
30.
31.
<?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@la.fr'
,
);
Une fois que c'est fait on peut utiliser le workbench :
La syntaxe est simple : le « vendor » est ici « bestmomo » et le paquetage s'appelle « formulor ». Regardons ce que le workbench a créé :
On a un nouveau dossier workbench/bestmomo/formulor qui contient quelques fichiers dont l'indispensable composer.json, un dossier src pour recevoir le code du paquetage avec pour le moment un seul fichier : FormulorServiceProvider.php, un dossier tests, et un dossier vendor avec composer et illuminate.
Par défaut le workbench crée un paquetage « agnostic », c'est-à-dire qu'il n'est pas spécialement adapté à Laravel. Pour obtenir un paquetage spécialement adapté à Laravel il faut ajouter l'option -resources, ce qui a pour effet de créer les dossiers config, lang, views, migrations… Dans notre cas on n'a pas besoin de ces dossiers, je n'ai donc pas utilisé cette option.
XXVI-A-1. Le fichier FormulorServiceProvider.php▲
Voici ce fichier tel qu'il a été créé par le workbench :
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.
<?php
namespace
Bestmomo\Formulor;
use
Illuminate\Support\ServiceProvider;
class
FormulorServiceProvider extends
ServiceProvider {
/**
* Indicates if loading of the provider is deferred.
*
*
@var
bool
*/
protected
$defer
=
false
;
/**
* Register the service provider.
*
*
@return
void
*/
public
function
register()
{
//
}
/**
* Get the services provided by the provider.
*
*
@return
array
*/
public
function
provides()
{
return
array
();
}
}
Il faut donc renseigner la méthode register qui est appelée dès que le paquetage est enregistré, et la méthode provides destinée à fournir le service :
2.
3.
4.
5.
6.
7.
8.
9.
10.
11.
12.
13.
14.
15.
16.
17.
18.
19.
20.
21.
22.
/**
* Register the service provider.
*
*
@return
void
*/
public function register()
{
$this
->
app[
'
formulor
'
]
=
$this
->
app->
share(function($app
)
{
return new Formulor;
}
);
}
/**
* Get the services provided by the provider.
*
*
@return
array
*/
public function provides()
{
return array('
formulor
'
);
}
La propriété app est une instance du conteneur de l'application. Ici on crée une liaison entre notre paquetage et l'application.
Il nous faut maintenant enregistrer notre provider dans le fichier app/config/app.php :
2.
3.
4.
'
Illuminate\View\ViewServiceProvider
'
,
'
Illuminate\Workbench\WorkbenchServiceProvider
'
,
'
Bestmomo\Formulor\FormulorServiceProvider
'
),
XXVI-A-2. Le code de formulor▲
Il nous faut maintenant coder notre formulor. Créons juste deux types color et date. On crée un fichier Bestmomo/Formulor/Formulor.php pour contenir notre classe :
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.
<?php
namespace
Bestmomo\Formulor;
use
Form;
class
Formulor {
/**
* Create a color input field.
*
*
@param
string
$name
*
@param
string
$value
*
@param
array
$options
*
@return
string
*/
public
function
color($name
,
$value
=
null
,
$options
=
array
())
{
return
Form::
input('color'
,
$name
,
$value
,
$options
);
}
/**
* Create a date input field.
*
*
@param
string
$name
*
@param
string
$value
*
@param
array
$options
*
@return
string
*/
public
function
date($name
,
$value
=
null
,
$options
=
array
())
{
return
Form::
input('date'
,
$name
,
$value
,
$options
);
}
}
Testons tout de suite ça en utilisant ce code dans le fichier app/routes.php :
echo $app
[
'
formulor
'
]->
color('
couleur
'
);
Commentons aussi le contenu de la route définie par défaut par Laravel. Vous obtenez ce résultat :
<input name
=
"couleur"
type
=
"color"
>
Pour le moment tout a l'air de bien se passer .
XXVI-A-3. La façade▲
On va maintenant créer la façade pour avoir un accès statique à notre classe. On crée un fichier Bestmomo/Formulor/FormulorFacade.php avec ce code :
2.
3.
4.
5.
6.
7.
8.
9.
10.
11.
12.
13.
14.
<?php
namespace
Bestmomo\Formulor;
use
Illuminate\Support\Facades\Facade;
class
FormulorFacade extends
Facade {
/**
* Get the registered name of the component.
*
*
@return
string
*/
protected
static
function
getFacadeAccessor() {
return
'formulor'
;
}
}
Et évidemment on déclare la façade dans le fichier app/config/app.php :
2.
3.
4.
'
Validator
'
=>
'
Illuminate\Support\Facades\Validator
'
,
'
View
'
=>
'
Illuminate\Support\Facades\View
'
,
'
Formulor
'
=>
'
Bestmomo\Formulor\FormulorFacade
'
),
Du coup on peut utiliser maintenant ce code dans le fichier app/routes.php :
echo Formulor::
color('
couleur
'
);
XXVI-A-4. Le fichier composer.json▲
Voyons à présent ce fichier généré par workbench :
2.
3.
4.
5.
6.
7.
8.
9.
10.
11.
12.
13.
14.
15.
16.
17.
18.
19.
20.
{
"name"
:
"bestmomo/formulor"
,
"description"
:
""
,
"authors"
:
[
{
"name"
:
"Bestmomo"
,
"email"
:
"bestmomo@la.fr"
}
],
"require"
:
{
"php"
:
">=5.3.0"
,
"illuminate/support"
:
"4.0.x"
},
"autoload"
:
{
"psr-0"
:
{
"Bestmomo\\Formulor"
:
"src/"
}
},
"minimum-stability"
:
"dev"
}
Nous voyons qu'il nous faut compléter la description, faisons-le :
"description"
:
"Des formulaires plus complets"
,
Voyons maintenant si le fichier est valide pour composer :
On nous reproche juste de ne pas avoir précisé de licence, complétons encore :
"license"
:
"BSD-2-Clause"
,
Et maintenant :
Notre paquetage est valide, nous pouvons le proposer . Pour ce faire il faudrait déjà le placer dans Github, et ensuite le proposer à Composer.
XXVI-A-5. Utilisation du paquetage directement▲
Vous n'êtes évidemment pas obligé de mettre votre paquetage à disposition, vous pouvez l'utiliser directement dans une application. Il suffit de créer un dossier vendor/bestmomo/formulor, avec les trois classes :
Il faut ensuite renseigner le fichier app/composer.json :
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.
{
"require"
:
{
"laravel/framework"
:
"4.0.*"
},
"autoload"
:
{
"classmap"
:
[
"app/commands"
,
"app/controllers"
,
"app/models"
,
"app/database/migrations"
,
"app/database/seeds"
,
"app/tests/TestCase.php"
,
"vendor/bestmomo/formulor"
]
},
"scripts"
:
{
"pre-update-cmd"
:
[
"php artisan clear-compiled"
],
"post-update-cmd"
:
[
"php artisan optimize"
]
},
"config"
:
{
"preferred-install"
:
"dist"
},
"minimum-stability"
:
"dev"
}
Ainsi nos classes seront prises en compte, mais il faut évidemment actualiser l'autoload (avec composer dumpautoload). On termine en renseignant le fichier app/config/app.php pour enregistrer le fournisseur et déclarer la façade comme nous l'avons fait précédemment.
XXVI-A-6. Un packetage avec CKEditor▲
Maintenant que nous avons vu comment créer un paquetage avec un exemple simple, voyons un cas plus réaliste. Vous connaissez sans doute l'éditeur CKEditor. C'est un éditeur Web puissant et esthétique. Son intégration à une page Web est facile et il comporte une multitude d'options. Nous allons créer un packetage pour rendre son intégration dans une vue encore plus facile.
Commencez par créer un workbench comme nous l'avons vu ci-dessus mais cette fois pour bestmomo/ckeditor. Voici le code pour le fichier Bestmomo/Ckeditor/Ckeditor.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.
30.
31.
32.
33.
34.
35.
36.
37.
38.
39.
40.
<?php
namespace
Bestmomo\Ckeditor;
use
Form,
HTML;
class
Ckeditor {
/**
* Variable booléenne pour indiquer si on a déjà créé un éditeur
*/
private
$initialized
=
false
;
/**
* Création d'un éditeur
*
*
@param
$name
(
string
) Nom de l'éditeur, et aussi le nom du textarea
*
@param
$value
(
string
) Valeur initiale (optionnel).
*
@param
$config
(
array
) Configuration pour cet éditeur (optionnel).
*
* Exemples :
*
*
$CKEditor
=
Ckeditor::
make("editor1", "
<
p
>
Une valeur
<
/p
>
");
*
*
$CKEditor
=
Ckeditor::
make("editor1", "
<
p
>
Une valeur
<
/p
>
", ,
array
('toolbar' => 'Basic', 'uiColor' => '#9AB8F3'));
*
*/
public
function
make($name
,
$value
=
''
,
$config
=
array
())
{
$out
=
''
;
if
(!
$this
->
initialized) {
$this
->
initialized =
true
;
$out
=
HTML::
script('ckeditor/ckeditor.js'
);
}
$out
.=
Form::
textarea($name
,
htmlspecialchars($value
));
$out
.=
"<script> CKEDITOR.replace(
\"$name\"
"
;
if
(!
empty($config
)) $out
.=
','
.
json_encode($config
);
$out
.=
" ); </script>
\n
"
;
return
$out
;
}
}
La variable $initialized est destinée à ne référencer qu'une fois la bibliothèque JavaScript si on met plusieurs éditeurs sur la même page. La méthode make génère le code nécessaire pour l'intégration d'un éditeur avec la possibilité d'avoir une valeur, et aussi de configurer l'éditeur.
Voici maintenant le fichier Bestmomo/Ckeditor/CkeditorServiceProvider :
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.
<?php
namespace
Bestmomo\Ckeditor;
use
Illuminate\Support\ServiceProvider;
class
CkeditorServiceProvider extends
ServiceProvider {
/**
* Indicates if loading of the provider is deferred.
*
*
@var
bool
*/
protected
$defer
=
false
;
/**
* Bootstrap the application events.
*
*
@return
void
*/
public
function
boot()
{
$this
->
package('bestmomo/ckeditor'
);
}
/**
* Register the service provider.
*
*
@return
void
*/
public
function
register()
{
$this
->
app[
'ckeditor'
]
=
$this
->
app->
share(function
($app
)
{
return
new
Ckeditor;
}
);
}
/**
* Get the services provided by the provider.
*
*
@return
array
*/
public
function
provides()
{
return
array
();
}
}
Et voici la façade Bestmomo/Ckeditor/CkeditorFacade :
2.
3.
4.
5.
6.
7.
8.
9.
10.
11.
12.
13.
14.
<?php
namespace
Bestmomo\Ckeditor;
use
Illuminate\Support\Facades\Facade;
class
CkeditorFacade extends
Facade {
/**
* Get the registered name of the component.
*
*
@return
string
*/
protected
static
function
getFacadeAccessor() {
return
'ckeditor'
;
}
}
Renseignez ensuite le fichier app/config/app.php :
2.
3.
4.
5.
6.
7.
8.
9.
10.
11.
'
Illuminate\View\ViewServiceProvider
'
,
'
Illuminate\Workbench\WorkbenchServiceProvider
'
,
'
Bestmomo\Ckeditor\CkeditorServiceProvider
'
),
...
'
Validator
'
=>
'
Illuminate\Support\Facades\Validator
'
,
'
View
'
=>
'
Illuminate\Support\Facades\View
'
,
'
Ckeditor
'
=>
'
Bestmomo\Ckeditor\CkeditorFacade
'
),
Pour tester tout ça, créez une vue app/views/home.blade.php :
Et enfin une route :
Normalement vous obtenez ce résultat :
Vous trouverez un exemple de paquetage plus complet mais en anglais ici.