Photo de Chandler Cruttenden sur Unsplash

Comment construire des applications modulaires à Laravel: L'approche Plug N Play - Partie 2

Dans la première partie de cet article sur «comment construire des applications modulaires dans Laravel», nous avons longuement discuté des modules et des avantages de la modularisation de vos applications. Vous pouvez trouver la partie de cet article ici "Comment construire des applications modulaires dans Laravel - Partie 1".

Dans cette seconde partie, nous allons parler un peu technique de l’utilisation des modules dans Laravel. Donc, sans perdre de temps, commençons par l’endroit où nous nous sommes arrêtés dès la première partie. On y va?

Note: S'il vous plaît, je vous conseillerais de lire jusqu'à la fin de cet article.

Création d'une migration dans un module

Les migrations sont comme un contrôle de version pour votre base de données, permettant à votre équipe de modifier et de partager facilement le schéma de base de données de l’application. Les migrations sont généralement associées au générateur de schéma de Laravel pour créer facilement le schéma de base de données de votre application.

Créer des migrations pour les modules n’est pas différent du tout. Pour créer une migration pour un module, utilisez le module module: make-migration Artisan command:

Module artisan php: make-migration create_customers_table Clients

La nouvelle migration sera placée dans votre répertoire Modules / Clients / base de données / migrations. Chaque nom de fichier de migration contient un horodatage identique à celui de la migration par défaut de Laravel, qui détermine l’ordre des migrations.

L'option Clients de la commande permet d'indiquer le nom du module sous lequel la migration doit être générée. Vous pouvez modifier le nom de n'importe quel module pour lequel vous générez une migration.

Exécution de migrations

Pour exécuter une seule migration de module en attente, exécutez la commande module: migrate Artisan:

Module artisan php: migrer les clients

Mais qu'en est-il des migrations pour tous vos modules avec une seule commande? Bien que nous soyons couverts comme la dernière partie de cet article.

Création de modèles pour un module

Nous savons tous que par défaut, Laravel fournit à Eloquent ORM une implémentation simple d'ActiveRecord pour travailler avec votre base de données. Chaque table de base de données a un «modèle» correspondant qui est utilisé pour interagir avec cette table. Les modèles vous permettent de rechercher des données dans vos tables, ainsi que d'insérer de nouveaux enregistrements dans la table.

C'est la même approche lorsque vous travaillez avec des modules dans Laravel.

Pour commencer, créons un modèle Eloquent pour notre module. Les modèles résident généralement dans le répertoire app par défaut, mais lors de l'utilisation de Modules, les modèles se trouvent dans le répertoire Modules / Customers / Entities. Les modèles Eloquent de tous les modules étendent également la classe Illuminate \ Database \ Eloquent \ Model.

Le moyen le plus simple de créer une instance de modèle pour votre module consiste à utiliser la commande module: make-model Artisan:

Module artisan php: make-model Client Clients

L'option Client de la commande ci-dessus est le nom du modèle, tandis que l'option Clients est le nom du module.

Si vous souhaitez générer une migration de base de données lors de la génération d'un modèle pour votre module, vous pouvez utiliser l'option -m:

Module artisan php: make-model Customer -m Clients

Assurez-vous de suivre la convention de nommage Laravel par défaut lors de la création de modèles.

Communiquer avec différents modèles

Normalement, lorsque vous utilisez le modèle par défaut de Laravel, il est facile de référencer un autre modèle. mais lors de l'utilisation de modules, l'implémentation est différente.

Implémentation par défaut

espace de noms App;
utilisez Illuminate \ Database \ Eloquent \ Model;
classe client étend le modèle
{
    fonction publique état ()
    {
     return $ this-> appartientTo ('App \ State', 'state_id');
    }
}

Vous pouvez voir dans le code ci-dessus qu'il est facile de référencer un autre modèle à partir d'un modèle particulier à l'aide de l'espace de nom de l'application. Voyons maintenant comment implémenter cela de manière modulaire.

Mise en œuvre modulaire

espace de noms App;
utilisez Illuminate \ Database \ Eloquent \ Model;
utilisez Modules \ Customers \ Entities \ State;
classe client étend le modèle
{
    fonction publique état ()
    {
        return $ this-> appartientTo (State :: class, 'state_id');
    }
}

Pouvez-vous repérer la différence? Dans l'exemple ci-dessus, le modèle d'état est situé dans le module Clients. Donc, pour utiliser la classe State dans le modèle Laravel par défaut, nous devons la référencer au module auquel elle appartient et au répertoire comme indiqué ci-dessus.

Mais lorsque vous vous trouvez dans le modèle d'un module et que vous souhaitez référencer une classe de modèle par défaut telle que le modèle utilisateur, l'exemple ci-dessous devrait vous guider:

espace de noms Modules \ Claims \ Entities;
utilisez Illuminate \ Database \ Eloquent \ Model;
classe client étend le modèle
{
    protected $ fillable = [];
    profil de fonction publique ()
    {
     return $ this-> appartientTo ('App \ User', 'insurance_company_id');
    }
}

Vous pouvez voir dans l'exemple ci-dessus que l'espace de nom est différent; C’est parce que nous sommes dans un modèle de module appelé Client. Ainsi, à partir du modèle d'un module, vous pouvez facilement référencer un modèle par défaut sans l'inclure d'abord avec le mot-clé use.

Utiliser les contrôleurs de manière modulaire

Définir les contrôleurs

Vous trouverez ci-dessous un exemple de classe de contrôleur de module de base. Notez que le contrôleur étend la classe de contrôleur de base incluse avec Laravel:

espace de noms Modules \ Claims \ Http \ Controllers;
utilisez Illuminate \ Http \ Request;
utilisez Illuminate \ Http \ Response;
utilisez Illuminate \ Routing \ Controller;
utilisez Modules \ Claims \ Entities \ Customer;
classe CustomersController étend Controller
{
    / **
     * Afficher une liste de la ressource.
     * Réponse de retour
     * /
    indice de fonction publique ()
    {
        retourne la vue ('clients :: client.index');
    }
    / **
     * Montrer le formulaire pour créer une nouvelle ressource.
     * Réponse de retour
     * /
    fonction publique create ()
    {
        retourner la vue ('claims :: customer.create');
    }
}

Il se passe beaucoup de choses qui pourraient vous dérouter au début, mais détendez-vous pendant que je vous explique:

L’espace de noms Modules \ Claims \ Http \ Controllers déclare simplement notre contrôleur comme faisant partie de l’espace de noms du contrôleur du module.

L'utilisation Modules \ Claims \ Entities \ Customer consiste simplement à inclure le modèle Client à notre contrôleur de module.

Alors que la vue de retour ('clients :: client.index') renvoie la réponse à la vue propre du module, pas à la vue Laravel par défaut.

Clients :: est le nom du module, alors que customer.index est un répertoire du dossier Resources-> views du module.

Ainsi, chaque fois que vous souhaitez rendre une vue faisant partie de l’espace de nom des vues du module, vous pouvez conserver l’approche ci-dessus. Mais si vous voulez rendre une vue Laravel par défaut, restez fidèle à la méthode traditionnelle, comme indiqué ci-dessous:

retourner la vue ('customers.index);

Créer un contrôleur

Pour créer un contrôleur pour vos modules, exécutez la commande ci-dessous:

Module artisan php: make-controller CustomersController Customer

Cette commande générera un contrôleur sous le répertoire Modules \ Http \ Controllers avec le nom CustomersController. Toute autre implémentation que vous souhaitez effectuer dans le contrôleur de votre module est identique à celle du contrôleur par défaut de Laravel, à l’exception de celles décrites ci-dessus.

Créer des semences

Laravel inclut une méthode simple permettant d'ensemencer votre base de données avec des données de test à l'aide de classes de départ. Toutes les classes de départ sont stockées dans le répertoire database / seed. Les classes de semences peuvent avoir le nom de votre choix, mais doivent probablement respecter certaines conventions judicieuses, telles que UsersTableSeeder, etc. Par défaut, une classe DatabaseSeeder est définie pour vous. À partir de cette classe, vous pouvez utiliser la méthode call pour exécuter d'autres classes de départ, ce qui vous permet de contrôler l'ordre d'ensemencement.

Mais lorsqu'il s'agit de modules, il y a de petites différences comme:

Création de semoirs

Pour générer un segment pour un module, exécutez la commande module: make-seeder Artisan. Tous les générateurs générés par le module seront placés dans le répertoire Modules \ Customers \ Database \ Seeders:

Module artisan php: make-seeder StatesTableSeeder Clients

Le code ci-dessus générera un fichier de base comme celui présenté ci-dessous:

espace de noms Modules \ Customers \ Database \ Seeders;
utilisez Illuminate \ Database \ Seeder;
utilisez Illuminate \ Database \ Eloquent \ Model;
Classe StatesDatabaseSeeder étend Seeder
{
    / **
     * Exécutez les graines de la base de données.
     *
     * @return void
     * /
    fonction publique run ()
    {
        Modèle :: unguard ();
        // $ this-> call ("OthersTableSeeder");
    }
}

Ayant la structure de code ci-dessus pour votre fichier de base, vous pouvez placer tous les codes que vous aimeriez ajouter juste en dessous de Model :: unguard ().

Exécuter les fichiers de départ de votre module

Après avoir préparé tous vos semences, assurez-vous que tous vos fichiers de départ sont déclarés dans le fichier de départ par défaut généré initialement lors de la création du module:

espace de noms Modules \ Customers \ Database \ Seeders;
utilisez Illuminate \ Database \ Seeder;
utilisez Illuminate \ Database \ Eloquent \ Model;
La classe CustomersDatabaseSeeder étend Seeder
{
    / **
     * Exécutez les graines de la base de données.
     *
     * @return void
     * /
    fonction publique run ()
    {
        Modèle :: unguard ();
        $ this-> call (StatesTableSeeder :: class);
        // tout autre semoir peut aller ici
    }
}

Ceci fait, vous pouvez exécuter le module: Commande Artisan de graine

Module artisan php: Clientèle semences

Le code ci-dessus exécutera tous les fichiers de départ sous le module Clients.

Utilisation des itinéraires dans les modules

Par défaut, tous les itinéraires Laravel sont définis dans vos fichiers d’itinéraire, qui se trouvent dans le répertoire itinéraires. Ces fichiers sont automatiquement chargés par le framework. Le fichier routes / web.php définit les itinéraires correspondant à votre interface Web. Le groupe de middleware Web est affecté à ces itinéraires. Il fournit des fonctionnalités telles que l'état de session et la protection CSRF.

Cette même structure s'applique lorsque vous travaillez avec des modules. Lorsque vous créez un module, un dossier Routes est automatiquement créé avec les fichiers api.php et web.php. Et aussi ces fichiers sont automatiquement chargés par le framework. Cela signifie que tous les itinéraires que vous déclarez à l'intérieur du fichier Modules \ Clients \ Routes \ web.php sont accessibles globalement.

Ci-dessous un fichier de route Web par défaut pour le module Clients

/ *
| ----------------------------------------------------- -------------------------
| Itinéraires Web
| ----------------------------------------------------- -------------------------
|
| Voici où vous pouvez enregistrer des itinéraires Web pour votre application. Celles-ci
| Les itinéraires sont chargés par RouteServiceProvider dans un groupe qui
| contient le groupe de middleware "web". Maintenant, créez quelque chose de grand!
|
* /
Route :: préfixe ('clients') -> groupe (fonction () {
    Route :: get ('/', 'CustomersController @ index');
});

Vous pouvez donc éditer le fichier de route en fonction de vos besoins.

Comment exécuter la migration de tous vos modules et de vos semences avec une seule commande Artisan

Au début, lorsque j'ai commencé à travailler avec les modules, j'ai découvert un défi. J'ai découvert qu'après la modularisation de mon application, il me restait plus de cinq modules à gérer. La gestion dans ce sens consiste à exécuter des migrations et des amorces pour chacun de ces modules au cours du développement et ce processus n’était pas vraiment efficace et prenait beaucoup de temps. Contrairement à la méthode par défaut consistant à exécuter une migration dans Laravel en utilisant une seule commande Artisan migrate, qui exécute toutes les migrations de votre application. il en va de même pour les semeurs.

J’ai donc écrit une commande Artisan personnalisée qui m’aidera à exécuter toutes les migrations et toutes les sources de mon module avec une seule commande. Ceci est également important en cas de déploiement.

Le fichier affiché ci-dessous devrait vous aider à créer le vôtre:

espace de noms App \ Console \ Commands;
utilisez Illuminate \ Console \ Command;
utilisez Symfony \ Component \ Console \ Input \ InputArgument;
utilisez Symfony \ Component \ Console \ Input \ InputOption;
classe AppRobot étend la commande
{
    / **
     * Le nom et la signature de la commande de la console.
     *
     * @var string
     * /
    protected $ signature = 'robot: run-migration';
/ **
     * La description de la commande de la console.
     *
     * @var string
     * /
    protected $ description = 'Cette commande exécute toutes les migrations du système et des sous-systèmes';
/ **
     * Créer une nouvelle instance de commande.
     *
     * @return void
     * /
    fonction publique __construct ()
    {
        parent :: __ construct ();
    }
/ **
     * Exécutez la commande de la console.
     *
     * retour mixte
     * /
    fonction publique handle ()
    {
        $ this-> call ('migrate', [
            '--force' => 'force',
        ]);
        $ this-> call ('module: migrer', [
            'module' => 'Clients',
        ]);
/ ** --------------- semeurs en cours d'exécution ----------------- ** /
        $ this-> call ('db: seed', [
            '--force' => 'force',
        ]);
        $ this-> call ('module: seed', [
            'module' => 'Clients',
        ]);
}

Jusqu'ici, basé sur ma propre expérience dans la construction d'applications modulaires à Laravel, j'aimerais vous conseiller de placer toute implémentation appartenant à Module dans ce répertoire Module. cas, etc. Cela lui permettra d'être facilement branché dans une autre application pour une utilisation.

Avec ceci, nous arrivons à la fin de cet article sur «Comment construire une application modulaire dans Laravel: parties 1 et 2». Avec ce qui est contenu dans ces deux parties, vous devriez pouvoir créer facilement votre propre application modulaire. Et s’il est nécessaire de créer une partie 3 de cet article, je le ferai car certains concepts ne sont pas abordés; comme utiliser des middlewares, des mails, des fournisseurs, etc.

N'oubliez pas de laisser vos commentaires ou contributions dans la section commentaires ci-dessous et applaudissez s'il vous plaît pour que les autres puissent trouver ce message rapidement.

Merci pour la lecture.