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.


