Singleton avec Laravel

Alors le but ici n’est pas d’utiliser la doc de Laravel, qui répond d’une manière précise sur l’usage du singleton. Le but est plus d’utiliser les outils de Laravel pour utiliser le Singleton d’une autre manière, sous forme de contrat. On va donc rendre une instance disponible dans toute l’application, en attachant (bind) une interface, à une (fake) implémentation, qui correspond à la classe désirée.

singleton laravel

Qu’est-ce que le Singleton ?

Le Singleton vous permet de ne pas avoir à instancier une classe sur les différents niveaux de votre application. C’est utile quand vous avez par exemple à gérer un contexte en fonction du nom de domaine, et que ce contexte n’est de toute façon pas voué à changer pendant la requête.
De la même manière, quand on vous propose une lib pour utiliser tel ou tel service, généralement vous devez faire un new SuperService(‘ma_cle_api’). Si vous allez utiliser ce service à plusieurs endroits dans votre application, voir même plusieurs fois pendant la même requête, alors le Singleton est là pour vous aider.

Les Services Providers à la rescousse

Reprenons le dernier cas d’usage. Dans notre cas on va parler de Mailchimp. Il existe une lib très cool pour utiliser leur APIv3.

la première étape consiste créer l’Interface

namespace App\Mailer\Contracts;

/**
 * Interface MarketingMailerInterface
 * @package App\Mailer\Contracts
 */
interface MarketingMailerInterface
{

}

Ensuite, on va créer le fournisseur de service (Service Provider) avec la commande php artisan make:provider MarketingMailerServiceProvider par exemple.

Voilà ce qu’on insère dedans dans le fichier créé dans app/Providers (si vous êtes sur laravel 5.*)

namespace App\Providers;

use App\Mailer\Contracts\MarketingMailerInterface;
use DrewM\MailChimp\MailChimp;
use Illuminate\Support\ServiceProvider;

class MarketingMailerServiceProvider extends ServiceProvider
{
    
    public function register()
    {
        $this->app['marketing-mailer'] = $this->app->share(function ($app) {

            return (new MailChimp(env('MAILCHIMP')));

        });

        $this->app->bind(MarketingMailerInterface::class, function ($app) {

            return $app['marketing-mailer'];

        });
    }
}

Alors pour expliquer un peu ce qu’il y a dans cette méthode register : Dans un premier temps, on va créer une clé supplémentaire dans l’application (marketing-mailer).
On dit ensuite que cette clé doit être égale au partage d’une nouvelle instance de la classe désirée. Dans cet exemple, on veut une nouvelle instance de la classe Mailchimp mise à disposition par la librairie.

Et pour terminer, il faut maintenant faire en sorte que l’interface créée plus haut, soit résolue en retournant ce qu’on vient de mettre dans $app[‘marketing-mailer’] juste avant.

L’usage final

Maintenant que tout est prêt, on n’a plus qu’à créer notre classe qui va gérer nos listes. Mais surtout, elle va nous permettre d’hériter des méthodes de la librairie, voir de les surcharger, et d’ajouter nos propres méthodes. Plus besoin de gérer la connexion à Mailchimp, elle est gérée dans tous les cas :

namespace App\Mailer\Transports;

use App\Mailer\Contracts\MarketingMailerInterface;

class Marketing
{
    private $provider;

    public function __construct()
    {
        $this->provider = app(MarketingMailerInterface::class);
    }

    /**
     * @return MarketingMailerInterface
     */
    public function lists()
    {
        return $this->provider->get('lists');
    }
}

Maintenant, si vous allez dans un controller, et que vous injectez App\Mailer\Transports\Marketing, vous aurez directement toutes les méthodes de manipulation de vos listes, campagnes, etc.
Ca fonctionne aussi très bien dans les Services, etc. Ca veut dire que maintenant, en utilisant la classe Marketing, suite à l’enregistrement d’un utilisateur par exemple, vous allez : L’ajouter à la liste, l’ajouter dans une campagne en automation, et le coller sur une liste de prospects à contacter rapidement, tout ça depuis la même instance.

Recherches utilisées pour trouver cet article :laravel model singleton optimisation
metrogeek

Laisser un commentaire