Laravel 4

Laravel 4 : chapitre 26 : Création d’un package

Pour ajouter des fonctionnalités à Laravel le plus simple est de créer un package. D’ailleurs Laravel est lui-même un package. Vous trouvez tous les packages utilisables avec composer sur le site Packagist. Par exemple on trouve Laravel ici sur ce site. Certains des packages sont destinés spécifiquement à Laravel 4, mais 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 packages qui soient 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é 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 package qui va rester élémentaire).

Commencez par créer une nouvelle installation de Laravel 4. Vous devez obtenir cette arborescence :

img47

Le workbench

Laravel nous offre un outil pratique pour créer un package : le workbench. Mais il va nous falloir d’abord renseigner deux éléments (nom et adresse email) dans le fichier app/config/workbench.php :

<?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 :

img48

La syntaxe est simple le « vendor » est ici « bestmomo » et le package s’appelle « formulor ». Regardons ce que le workbench a créé :

img49

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 package 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 package « agnostic », c’est à dire pas spécialement adapté à Laravel. Pour obtenir un package 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 a pas besoin de ces dossiers, je n’ai donc pas utilisé cette option.

Le fichier FormulorServiceProvider.php

Voici ce fichier tel qu’il a été créé par le workbench :

<?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 package est enregistré et la méthode provides destinée à fournir le service :

/**
 * 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 package et l’application.

Il nous faut maintenant enregistrer notre provider dans le fichier app/config/app.php :

		'Illuminate\View\ViewServiceProvider',
		'Illuminate\Workbench\WorkbenchServiceProvider',
		'Bestmomo\Formulor\FormulorServiceProvider'
	),

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 :

<?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');

Commentez 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 Smile.

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 :

<?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 :

		'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');

Le fichier composer.json

Voyons à présent ce fichier généré par workbench :

{
    "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 :

img50

On nous reproche juste de ne pas avoir précisé de licence, complétons encore :

"license": "BSD-2-Clause",

Et maintenant :

img51

Notre package est valide, nous pouvons le proposer Laughing. Pour ce faire il faudrait déjà le placer dans github, et ensuite le proposer à composer.

Utilisation du package directement

Vous n’êtes évidemment pas obligé de mettre votre package a disposition, vous pouvez l’utiliser directement dans une application. Il suffit de créer un dossier vendor/bestmomo/formulor, avec les 3 classes :

img54

Il faut ensuite renseigner le fichier app/composer.json :

{
	"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 provider et déclarer la façade comme nous l’avons fait précédemment.

Un package avec CKEditor

Maintenant que nous avons vu comment créer un package 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 package 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 :

<?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 librairie 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 :

<?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 :

<?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 :

		'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 :

<!DOCTYPE html>
<head>
  <meta charset="utf-8">
  <title>Test de CKeditor</title>
</head>

<body>
  {{ $editor }}
</body>

Et enfin une route :

Route::get('/', function()
{
	$editor1 = Ckeditor::make('test1', 'texte1', array('toolbar' => 'Basic', 'uiColor' => '#9AB8F3'));
	$editor2 = Ckeditor::make('test2', 'texte2');
	return View::make('home')->with('editor', $editor1.$editor2);
});

Normalement vous obtenez ce résultat :

img58

Vous trouverez un exemple de package plus complet mais en anglais ici.

Print Friendly, PDF & Email

2 commentaires

Laisser un commentaire