Image Principale

Créer ses propres classes avec Laravel


Dans cet article, nous verrons comment il est possible de créer ses propres classes et de les intégrer proprement dans une application basée sur le framework PHP Laravel

Quand j'ai commencé sur Laravel et que j'ai voulu commencer à créer mes propres outils pour faire marcher mon application, j'ai eu du mal à comprendre comment je pouvais organiser mon code et créer de nouvelles classes.

Dans cet article, je vais essayer de vous décrire le plus simplement possible la création de ces classes et leur incorporation dans notre code.

Pour cet article, je vais créer une classe qui me permettra de proposer à un utilisateur d'autres utilisateurs qu'il pourrait aimer suivre. Un peu ce dont Twitter aurait besoin pour vous afficher une liste de suggestion de comptes à suivre. Bien sûr, ici on ne parlera que du mécanisme pour renvoyer des utilisateurs et pas d'un bon algorithme qui pourrait faire le travail recherché.

Pour commencer, il est nécessaire de vous trouver un petit nom de package pour le service que vous voulez créer. Le mien s'appellera Advisor parce que c'est cette classe qui me conseillera pour envoyer les bonnes suggestions aux utilisateurs.

Commençons par créer notre classe dans app\Services\Advisor\Advisor.php:

<?php
namespace App\Services\Advisor;

class Advisor 
{

}

Pour faire simple, je vais uniquement créer une méthode nommée findUsersForUser() qui sera chargée d'aller me chercher des utilisateurs pour un utilisateur donné:

<?php
namespace App\Services\Advisor;

use App\User;

class Advisor
{
    public function findUsersForUser(User $user)
    {

    }
}

Pour l'instant, cette méthode va tout le temps retourner les 5 derniers utilisateurs inscrits sur notre application, quelque soit l'utilisateur envoyé en paramètre:

public function findUsersForUser(User $user)
{
    return User::take(5)->orderBy('created_at','desc')->get();
}

La prochaine étape pour utiliser notre classe est de créer un Service Provider. Ces Services Providers permettent de charger des classes dans notre application. Ainsi, on n'aura besoin d'instancier qu'une seule fois ces classes. On créé donc une telle classe app/Services/Advisor/AdvisorServiceProvider.php:

<?php
namespace App\Services\Advisor;

use Illuminate\Support\ServiceProvider;

class AdvisorServiceProvider extends ServiceProvider
{

}

Pour que Laravel puisse correctement initialiser votre classe, il est nécessaire d'implémenter la méthode register() dans notre Service Provider. Cette méthode, sera chargée de placer notre classe dans le Service Container de notre application. Ce Service Container contient tous les services de notre application:

public function register()
{
    $this->app->singleton('Advisor', function($app) {
        return new Advisor();
    });
}

Il ne reste plus qu'à enregistrer notre Service Provider dans le Service Container de notre application en nous rendant dans le fichier config/app.php. Cherchez l'array providers, et ajoutez ici votre nouveau Service Provider:

<?php

return [

    ...

    'providers' => [

        ...
        App\Services\Advisor\AdvisorServiceProvider::class,
        ...

    ],

    ...

];

Rien que là, vous pouvez déjà accéder à votre fonction depuis un controller en appelant le Service Container de votre application. Plusieurs solutions s'offrent à vous:

L'injection de dépendances

L'injection de dépendances va vous permettre très simplement d'accéder à votre service depuis le constructeur de votre controller. Pour cela, il suffit de mettre en paramètre du constructeur du controller une variable typée de la classe que vous venez de configurer dans votre Service Provider:

<?php

namespace App\Http\Controllers;

use App\Services\Advisor\Advisor;

class UsersController extends Controller
{
    public function __construct(Advisor $advisor)
    {
        dd($advisor);
    }
}

L'accès au Service Container

Une variable $app contient tous vos services. Il est donc possible de l'appeler et de lui demander la fonction recherchée. Pour cela, un helper a été créé pour nous faciliter la tâche. De n'importe quel endroit de votre controller, vous pouvez faire la chose suivante:

dd(app(Advisor::class));

En veillant bien sûr à toujours avoir le use App\Services\Advisor\Advisor; en haut de votre fichier.

Une autre manière est d'appeler notre classe comme suit:

dd(app()[Advisor::class]);

Création d'une Facade

L'accès par le service container fonctionne très bien. Mais le créateur de Laravel, Taylor Otwell nous donne l'occasion d'accéder bien plus facilement à ces classes. Rassurez-vous, notre Facade utilisera le Service Provider que nous venons de créer. Pour cela, il va nous falloir créer une dernière classe app/Services/Advisor/AdvisorFacade.php. Ce fichier sera très simple:

<?php
namespace App\Services\Advisor;

use Illuminate\Support\Facades\Facade;

class AdvisorFacade extends Facade
{
    protected static function getFacadeAccessor()
    {
        return Advisor::class;
    }
}

Comme vous le voyez, notre Facade doit implémenter la fonction getFacadeAccessor qui doit retourner notre classe Advisor. Mais attention, comme vous le voyez, nous ne renvoyons pas une nouvelle instance new Advisor() mais bien Advisor::class qui est la référence de notre classe dans le Service Container. Cette référence, nous l'avons indiquée dans notre ServiceProvider dans la méthode register().

Il ne nous reste plus qu'à indiquer à Laravel que nous voulons utiliser notre nouvelle Facade. Encore une fois, il est nécessaire de se rendre dans le fichier config/app.php et d'indiquer dans l'array adéquat où se trouve votre Facade:

<?php

return [

    ...

    'aliases' => [

        ....

        'Advisor' => App\Services\Advisor\AdvisorFacade::class,
    ],

];

Vous pouvez maintenant utiliser cette Facade dans n'importe quel fichier en l'appelant de la manière suivante:

<?php

namespace App\Http\Controllers;

use Advisor;

class UsersController extends Controller
{

    public function __construct()
    {
        dd(Advisor::findUsersForUser(User::first()));
    }
}