Ir al contenido
Bondry

Anatomía de un módulo y module.json

La estructura de carpetas, cada campo del manifiesto, y los métodos del ciclo de vida que llama el kernel.

Un módulo es un directorio autocontenido, cargable en tiempo de ejecución e instalable desde un zip. Los módulos de fábrica usan exactamente este contrato.

Estructura de carpetas#

Código
modules/directory/
  module.json                 manifiesto (obligatorio)
  src/
    DirectoryServiceProvider.php
    Models/
    Http/Controllers/
    Http/Requests/
    Support/
  database/
    migrations/               las tablas del módulo
    seeders/
  resources/
    views/                    Blade, sobreescribible por un tema
    lang/                     las traducciones del módulo
    assets/                   css y js, YA COMPILADOS
  routes/
    web.php
    admin.php
  config/directory.php

El manifiesto#

JSON
{
  "name": "Directory",
  "slug": "directory",
  "version": "1.2.0",
  "description": "A configurable catalogue.",
  "author": { "name": "You", "url": "https://example.com" },
  "requires": {
    "bondry": ">=1.0 <2.0",
    "php": ">=8.2",
    "extensions": ["gd"],
    "modules": { "payments": ">=1.0" }
  },
  "provider": "Modules\\Directory\\DirectoryServiceProvider",
  "provides": {
    "permissions": ["directory.view", "directory.manage"],
    "hooks": ["profile.tabs", "admin.menu", "search.sources"]
  },
  "settings": "admin.directory.settings",
  "assets": { "css": ["assets/directory.css"], "js": ["assets/directory.js"] },
  "parent": null,
  "tested_up_to": "1.4.0",
  "official": false,
  "licensing": { "product_slug": "your-directory" }
}
Campo Significado
slug La identidad. [a-z0-9-], único, y nunca cambia entre versiones.
version Semver. Es lo que impulsa onUpdate.
requires Rangos semver. El kernel se niega a instalar cuando no se cumplen.
provider La clase raíz. Tiene que existir y extender el provider base.
provides.permissions Se registran en la matriz de grupos al instalar.
settings Un nombre de ruta. El listado de módulos enlaza a él cuando el módulo está activo.
parent El slug del módulo que este extiende. Ausente significa que extiende el core.
tested_up_to La versión más nueva del core contra la que probaste.
official Solo se acepta para paquetes firmados por nosotros.
licensing.product_slug Presente solo en un módulo de pago. Ver License API.

El service provider#

Tu provider extiende Bondry\Kernel\Modules\ModuleServiceProvider e implementa el ciclo de vida:

PHP
interface ModuleContract
{
    // Cada request, solo mientras el módulo está activo:
    public function register(): void;   // bindings del container
    public function boot(): void;       // rutas, vistas, migraciones, traducciones, hooks

    // Llamado por el instalador en tiempo de ejecución, no en cada request:
    public function onInstall(): void;
    public function onUninstall(bool $purge): void;
    public function onEnable(): void;
    public function onDisable(): void;
    public function onUpdate(string $from, string $to): void;
}

boot() es donde llamas a loadRoutesFrom, loadViewsFrom con tu namespace, loadMigrationsFrom, loadTranslationsFrom y registras tus hooks.

register() corre antes de que se resuelva nada: solo bindings, sin base de datos.

Advertencia boot() corre en cada request. Cualquier cosa costosa ahí es un costo que tus compradores pagan en cada vista de página, en hosting compartido.

Vistas y el tema#

Registra tus vistas con un namespace:

PHP
$this->loadViewsFrom(__DIR__.'/../resources/views', 'directory');

Renderizar directory::item.show resuelve entonces primero a través de la cadena de temas, así que un comprador puede sobrescribir cualquier pantalla de tu módulo desde su tema sin editar tus archivos. Ver Temas.

Flujo de instalación#

Lo que hace el panel con tu zip, en orden:

  1. lo abre en un directorio temporal aislado;
  2. lee module.json y valida el schema;
  3. revisa requires y cualquier conflicto de slug o versión;
  4. verifica la firma cuando official está activado;
  5. lo mueve a modules/<slug>/ y corre onInstall(), o onUpdate() cuando ya había una versión ahí;
  6. publica los assets en public/modules/<slug>/;
  7. lo registra en la tabla de módulos;
  8. limpia las cachés de rutas, vistas y configuración.