I. FormBuilder▲
I-A. Installation▲
L'installation de ce composant se fait de façon classique à partir de composer.json :
2.
3.
4.
"require"
:
{
"laravel/framework"
:
"5.1.*"
,
"laravelcollective/html"
:
"5.1.*"
},
Il suffit ensuite de faire un composer update pour charger le composant et mettre à jour le chargement automatique des classes. On a alors le composant présent dans le dossier vendor :
Il faut aussi prévoir de signaler à Laravel que ce composant existe dans config/app.php :
2.
3.
4.
5.
'
providers
'
=>
[
// ...
Collective\Html\HtmlServiceProvider::
class,
// ...
],
Mais vous ne trouverez pas cette ligne de code dans l'application pour une raison que nous allons voir au prochain chapitre.
Il faut aussi enregistrer les façades :
Avec tout ça, le composant est directement utilisable dans les vues.
I-B. Les macros▲
La façon la plus classique d'étendre les possibilités des classes FormBuilder et HtmlBuilder est d'utiliser des macros.
En effet si on regarde la classe FormBuilder par exemple :
2.
3.
class FormBuilder {
use
Macroable;
On trouve la déclaration du trait Macroable. Ce trait fait partie de Laravel :
Il donne la possibilité de créer des macros pour la classe concernée. Par exemple :
On peut alors l'utiliser dans une vue :
{!!
Form::
specialField() !!}
J'ai choisi de ne pas utiliser cette possibilité, mais de plutôt étendre la classe FormBuilder.
I-C. Étendre FormBuilder▲
Vous trouverez dans les services le dossier Html :
La classe FormBuilder étend celle du composant :
2.
3.
<?php
namespace
App\Services\Html;
class
FormBuilder extends
\Collective\Html\FormBuilder {
L'initialisation se fait dans le provider HtmlServiceProvider qui étend lui aussi le provider du composant :
2.
3.
4.
5.
6.
7.
8.
9.
10.
11.
12.
13.
14.
15.
16.
17.
18.
19.
20.
<?php
namespace
App\Services\Html;
class
HtmlServiceProvider extends
\Collective\Html\HtmlServiceProvider {
/**
* Register the form builder instance.
*
*
@return
void
*/
protected
function
registerFormBuilder()
{
$this
->
app->
bindShared('form'
,
function
($app
)
{
$form
=
new
FormBuilder($app
[
'html'
],
$app
[
'url'
],
$app
[
'session.store'
]->
getToken());
return
$form
->
setSessionStore($app
[
'session.store'
]
);
}
);
}
}
En effet, on veut seulement surcharger la méthode registerFormBuilder pour que le conteneur de Laravel instancie la classe du service au lieu de celle du composant.
Il faut aussi prévoir de signaler à Laravel que ce composant existe dans config/app.php :
2.
3.
4.
5.
'
providers
'
=>
[
// ...
App\Services\Html\HtmlServiceProvider::
class,
// ...
],
L'intendance est ainsi en place et il ne reste plus qu'à coder la classe et l'utiliser.
I-D. Les méthodes ajoutées▲
I-D-1. Bouton de soumission▲
Comme il y a de nombreux formulaires, on retrouve autant de fois le bouton de soumission. Son code de base est celui-ci :
L'astérisque représente une classe de la grille de Bootstrap. Voici en conséquence le code de la méthode pour générer le bouton :
Le deuxième paramètre est un tableau pour correspondre à la signature de la méthode de la classe parente.
Voici un cas d'utilisation avec le paramètre renseigné :
{!!
Form::
submit(trans('front/form.send'
),
[
'col-lg-12'
]
) !!}
I-D-2. Bouton de suppression▲
On a aussi plusieurs fois la présence d'un bouton de suppression avec ce code :
<
input class
=
"
btn btn-danger btn-block
"
type
=
"
submit
"
value
=
"
*
"
onclick
=
"
return confirm(*)
"
>
Les astérisques représentent les valeurs variables. Voici le code de la méthode :
Avec un cas d'utilisation :
{!!
Form::
destroy(trans('back/blog.destroy'
),
trans('back/blog.destroy-warning'
)) !!}
I-D-3. Les contrôles▲
Il y a de nombreux contrôles utilisés dans les formulaires de l'application. Ils ont tous la même structure :
Cette fois on a pas mal d'astérisques parce que les possibilités sont très variées. Voici la méthode correspondante :
2.
3.
4.
5.
6.
7.
8.
9.
10.
11.
12.
13.
14.
15.
16.
17.
18.
public function control($type
,
$colonnes
,
$nom
,
$errors
,
$label
=
null,
$valeur
=
null,
$pop
=
null,
$placeholder
=
''
)
{
$attributes
=
[
'
class
'
=>
'
form-control
'
,
'
placeholder
'
=>
$placeholder
];
return sprintf('
<div class="form-group %s %s">
%s
%s
%s
%s
</div>
'
,
($colonnes
==
0
)?
''
:
'
col-lg-
'
.
$colonnes
,
$errors
->
has($nom
) ?
'
has-error
'
:
''
,
$label
?
$this
->
label($nom
,
$label
,
[
'
class
'
=>
'
control-label
'
]
) :
''
,
$pop
?
'
<a href="#" tabindex="0" class="badge pull-right" data-toggle="popover" data-trigger="focus" title="
'
.
$pop
[
0
]
.
'
" data-content="
'
.
$pop
[
1
]
.
'
"><span>?</span></a>
'
:
''
,
call_user_func_array([
'
Form
'
,
$type
],
($type
==
'
password
'
)?
[
$nom
,
$attributes
]
:
[
$nom
,
$valeur
,
$attributes
]
),
$errors
->
first($nom
,
'
<small class="help-block">:message</small>
'
)
);
}
Ça permet des vues très épurées, par exemple :
2.
3.
{!!
Form::
control('text'
,
6
,
'name'
,
$errors
,
trans('front/contact.name'
)) !!}
{!!
Form::
control('email'
,
6
,
'email'
,
$errors
,
trans('front/contact.email'
)) !!}
{!!
Form::
control('textarea'
,
12
,
'message'
,
$errors
,
trans('front/contact.message'
)) !!}
Ce qui génère ceci :
2.
3.
4.
5.
6.
7.
8.
9.
10.
11.
12.
<
div class
=
"
form-group col-lg-6
"
>
<
label class
=
"
control-label
"
for
=
"
name
"
>
Votre nom<
/label
>
<
input id
=
"
name
"
class
=
"
form-control
"
type
=
"
text
"
name
=
"
name
"
placeholder
=
""
>
<
/div
>
<
div class
=
"
form-group col-lg-6
"
>
<
label class
=
"
control-label
"
for
=
"
email
"
>
Votre Email<
/label
>
<
input id
=
"
email
"
class
=
"
form-control
"
type
=
"
email
"
name
=
"
email
"
placeholder
=
""
>
<
/div
>
<
div class
=
"
form-group col-lg-12
"
>
<
label class
=
"
control-label
"
for
=
"
message
"
>
Votre message<
/label
>
<
textarea id
=
"
message
"
class
=
"
form-control
"
rows
=
"
10
"
cols
=
"
50
"
name
=
"
message
"
placeholder
=
""
></textarea
>
<
/div
>
I-D-4. Case à cocher▲
On a aussi quelques fois une case à cocher avec ce code :
Voici la méthode :
Et un cas d'utilisation :
{!!
Form::
check('memory'
,
trans('front/login.remind'
)) !!}
I-D-5. Liste▲
On a aussi des listes avec du code dans ce genre :
Voici la méthode :
2.
3.
4.
5.
6.
7.
8.
9.
10.
11.
public function selection($nom
,
$list
=
[],
$selected
=
null,
$label
=
null)
{
return sprintf('
<div class="form-group" style="width:200px;">
%s
%s
</div>
'
,
$label
?
$this
->
label($nom
,
$label
,
[
'
class
'
=>
'
control-label
'
]
) :
''
,
parent::
select($nom
,
$list
,
$selected
,
[
'
class
'
=>
'
form-control
'
]
)
);
}
Et un cas d'utilisation :
{!!
Form::
selection('role'
,
$select
,
$user
->
role_id,
trans('back/users.role'
)) !!}
Avec ce code généré :
Toutes les méthodes créées pourraient évidemment l'être différemment. Le seul but est de fournir un exemple de réalisation.
II. Les vues partielles▲
Il est souvent judicieux pour éviter les répétitions de code d'utiliser des vues partielles. Regardez le template du front-end :
On y trouve le code :
On voit que si on veut afficher une barre d'erreur, on appelle la vue partielle partials/error en lui transmettant des variables. Voici cette vue partielle :
2.
3.
4.
5.
6.
7.
<
div class
=
"
alert alert-
{{
$type
}}
alert-dismissible
"
role
=
"
alert
"
>
<
button type
=
"
button
"
class
=
"
close
"
data-dismiss
=
"
alert
"
>
<
span aria-hidden
=
"
true
"
>
×<
/span
>
<
span class
=
"
sr-only
"
>
Close<
/span
>
<
/button
>
{!!
$message
!!}
<
/div
>
On évite ainsi de répéter le code de mise en forme de la barre de Bootstrap.
On a aussi deux vues partielles dans le back-end :
Le principe est le même. Par exemple la vue partielle pannel.blade.php est destinée à mettre en forme un petit panneau de l'administration :
2.
3.
4.
5.
6.
7.
8.
9.
10.
11.
12.
13.
14.
15.
16.
17.
18.
19.
20.
21.
22.
<
div class
=
"
col-lg-4 col-md-6
"
>
<
div class
=
"
panel panel-
{{
$color
}}
"
>
<
div class
=
"
panel-heading
"
>
<
div class
=
"
row
"
>
<
div class
=
"
col-xs-3
"
>
<
span class
=
"
fa fa-
{{
$icone
}}
fa-5x
"
></span
>
<
/div
>
<
div class
=
"
col-xs-9 text-right
"
>
<
div class
=
"
huge
"
>
{{
$nbr
[
'new'
]
}}
<
/div
>
<
div>
{{
$name
}}
<
/div
>
<
/div
>
<
/div
>
<
/div
>
<
a href
=
"
{{
$url
}}
"
>
<
div class
=
"
panel-footer
"
>
<
span class
=
"
pull-left
"
>
{{
$nbr
[
'total'
]
.
' '
.
$total
}}
<
/span
>
<
span class
=
"
pull-right fa fa-arrow-circle-right
"
></span
>
<
div class
=
"
clearfix
"
></div
>
<
/div
>
<
/a
>
<
/div
>
<
/div
>
Ainsi avec les deux vues partielles la vue index de l'administration est légère et lisible :
2.
3.
4.
5.
6.
7.
8.
9.
10.
11.
12.
13.
14.
15.
16.
17.
18.
19.
@extends
('back.template'
)
@section
('main'
)
@
include('back.partials.entete'
,
[
'title'
=>
trans('back/admin.dashboard'
),
'icone'
=>
'dashboard'
,
'fil'
=>
trans('back/admin.dashboard'
)]
)
<
div class
=
"
row
"
>
@
include('back/partials/pannel'
,
[
'color'
=>
'primary'
,
'icone'
=>
'envelope'
,
'nbr'
=>
$nbrMessages
,
'name'
=>
trans('back/admin.new-messages'
),
'url'
=>
'contact'
,
'total'
=>
trans('back/admin.messages'
)]
)
@
include('back/partials/pannel'
,
[
'color'
=>
'green'
,
'icone'
=>
'user'
,
'nbr'
=>
$nbrUsers
,
'name'
=>
trans('back/admin.new-registers'
),
'url'
=>
'user'
,
'total'
=>
trans('back/admin.users'
)]
)
@
include('back/partials/pannel'
,
[
'color'
=>
'yellow'
,
'icone'
=>
'pencil'
,
'nbr'
=>
$nbrPosts
,
'name'
=>
trans('back/admin.new-posts'
),
'url'
=>
'blog'
,
'total'
=>
trans('back/admin.posts'
)]
)
@
include('back/partials/pannel'
,
[
'color'
=>
'red'
,
'icone'
=>
'comment'
,
'nbr'
=>
$nbrComments
,
'name'
=>
trans('back/admin.new-comments'
),
'url'
=>
'comment'
,
'total'
=>
trans('back/admin.comments'
)]
)
<
/div
>
@stop
Organiser ainsi les vues n'est pas forcément facile parce que les combinaisons sont nombreuses. Il faut s'efforcer de faire le plus simple possible.
III. Remerciements▲
Nous remercions Maurice Chavelli qui nous autorise à publier ce tutoriel.
Nous tenons également à remercier Winjerome pour la mise au gabarit et Claude Leloup pour la correction orthographique.