Skip to main content

2. Herramientas de generación de código

2.1. Introducción al comando "artesano"

El framework incluye una herramienta de línea de comandos llamada "artesano" que facilita la creación de código repetitivo y estructurado. Esta herramienta te ahorra tiempo y reduce errores al generar automáticamente archivos con una estructura consistente.

La herramienta "artesano" se encuentra en la raíz del proyecto y se ejecuta con PHP:

php artesano [comando] [argumentos]

Los principales comandos disponibles son:

  • create-legacy-infrastructure (alias: cli): Para crear conexiones con sistemas legacy de Quartup
  • create-domain (alias: cd): Para crear dominios de API completos

Estos comandos generan código siguiendo las convenciones del framework, manteniendo la coherencia en todo el proyecto.

2.2. Creando una infraestructura con CLI (create-legacy-infrastructure)

El comando create-legacy-infrastructure genera la capa de acceso a datos para interactuar con tablas del sistema legacy Quartup.

2.2.1. Parámetros y opciones

La sintaxis del comando es:

php artesano create-legacy-infrastructure [modulo] [recurso] [tabla]

Donde:

  • [modulo]: Es el módulo de Quartup (por ejemplo: p-maes, p-pos, p-vtas)
  • [recurso]: Es el nombre amigable que quieres darle al recurso (por ejemplo: productos, clientes, ventas)
  • [tabla]: Es el nombre real de la tabla en Quartup (por ejemplo: maesarti, poscli, venfaccab)

2.2.2. Archivos generados y su propósito

El comando genera dos archivos esenciales:

  1. Model: src/Infrastructures/Legacy/{ModuloCamel}/{TablaCamel}{RecursoCamel}/{TablaCamel}{RecursoCamel}Model.php

    Este archivo define la conexión con la tabla de Quartup y contiene:

    • La referencia a la tabla
    • Configuraciones específicas para la conexión
    namespace Infrastructures\Legacy\PMaes\MaesartiProductos;

    use App\Base\DB\BaseModelTree as Model;

    class MaesartiProductosModel extends Model
    {
    public $table = 'maesarti';

    public function __construct()
    {
    parent::__construct();
    }
    }
  2. Repository: src/Infrastructures/Legacy/{ModuloCamel}/{TablaCamel}{RecursoCamel}/{TablaCamel}{RecursoCamel}Repository.php

    Este archivo proporciona métodos para realizar operaciones en la tabla:

    • Consultas personalizadas
    • Operaciones CRUD básicas
    • Métodos específicos para casos de uso comunes
    namespace Infrastructures\Legacy\PMaes\MaesartiProductos;

    use App\Base\Repository;

    class MaesartiProductosRepository extends Repository
    {
    protected $model;

    public function __construct(MaesartiProductosModel $model)
    {
    $this->model = $model;
    }
    }

2.2.3. Ejemplo paso a paso

Vamos a crear una infraestructura para acceder a clientes en el sistema Quartup:

  1. Ejecutamos el comando:

    php artesano create-legacy-infrastructure p-pos clientes poscli
  2. Esto generará:

    • src/Infrastructures/Legacy/PPos/PoscliClientes/PoscliClientesModel.php
    • src/Infrastructures/Legacy/PPos/PoscliClientes/PoscliClientesRepository.php
  3. Los archivos generados están listos para usar y no requieren modificaciones adicionales.

  4. Podemos extender el repositorio si necesitamos consultas específicas:

    // Añadimos un método personalizado al repositorio
    public function findByEmail($email)
    {
    return $this->selectOne(['email' => $email]);
    }

2.3. Creando un dominio con CD (create-domain)

El comando create-domain genera una API completa para un recurso, incluyendo controlador, servicio, rutas y DTOs.

2.3.1. Parámetros y opciones

La sintaxis del comando es:

php artesano create-domain [dominio] [infraestructura] [modulo]

Donde:

  • [dominio]: Nombre del dominio en singular (por ejemplo: Product, Customer, Order)
  • [infraestructura]: Referencia a la infraestructura legacy en formato ModuloCamel_TablaCamelRecursoCamel (por ejemplo: PMaes_MaesartiProductos)
  • [modulo] (opcional): Si quieres crear el dominio dentro de un módulo específico

2.3.2. Archivos generados y su propósito

El comando genera varios archivos que conforman un CRUD completo:

  1. Controller: src/ApiLayer/Domains/{Dominio}s/{Dominio}sController.php

    Maneja las peticiones HTTP y aplica validaciones:

    class ProductsController extends DomainController
    {
    protected $productsService;

    public function __construct(ProductsService $service)
    {
    parent::__construct($service);

    // Definición de validaciones
    $this->validations = [
    'headers' => [],
    'body' => [],
    ];
    }
    }
  2. Service: src/ApiLayer/Domains/{Dominio}s/{Dominio}sService.php

    Contiene la lógica de negocio:

    class ProductsService extends DomainService
    {
    protected $maesartiProductosRepository;
    protected $resMaesartiProductosDTO;
    protected $reqMaesartiProductosDTO;

    public function __construct(
    MaesartiProductosRepository $maesartiProductosRepository,
    ResMaesartiProductosDTO $resMaesartiProductosDTO,
    ReqMaesartiProductosDTO $reqMaesartiProductosDTO
    ) {
    $this->maesartiProductosRepository = $maesartiProductosRepository;
    $this->resMaesartiProductosDTO = $resMaesartiProductosDTO;
    $this->reqMaesartiProductosDTO = $reqMaesartiProductosDTO;
    $this->maesartiProductosRepository->selectable(ResMaesartiProductosDTO::$selectables);
    }

    // Métodos de servicio para index, selectById, store, update, delete
    }
  3. Routes: src/ApiLayer/Domains/{Dominio}s/{Dominio}sRoutes.php

    Define las rutas RESTful:

    $middlewares = ['before' => [AuthMiddleware::class]];
    Route::group(ProductsController::class, function () use ($middlewares) {
    Route::get('products/', 'index', $middlewares);
    Route::get('products/:id', 'show', $middlewares);
    Route::post('products/', 'store', $middlewares);
    Route::put('products/:id', 'update', $middlewares);
    Route::delete('products/:id', 'delete', $middlewares);
    });
  4. DTOs:

    • Request DTO para mapeo de entradas: src/ApiLayer/Domains/{Dominio}s/DTOs/Req{Infraestructura}DTO.php
    • Response DTO para mapeo de salidas: src/ApiLayer/Domains/{Dominio}s/DTOs/Res{Infraestructura}DTO.php
    // DTO de respuesta
    class ResMaesartiProductosDTO extends ResDto
    {
    public static $selectables = [
    'nombre',
    'cod_articulo',
    ];

    // Propiedades y métodos
    }

    // DTO de petición
    class ReqMaesartiProductosDTO extends ReqDto implements InterfaceReqDto
    {
    protected $mapFilters = [
    'name' => 'nombre',
    ];

    // Métodos para transformación de datos
    }

2.3.3. Ejemplo paso a paso

Vamos a crear un dominio para gestionar clientes:

  1. Primero creamos la infraestructura (si no la tenemos ya):

    php artesano create-legacy-infrastructure p-pos clientes poscli
  2. Luego creamos el dominio:

    php artesano create-domain Customer PPos_PoscliClientes
  3. Esto generará:

    • src/ApiLayer/Domains/Customers/CustomersController.php
    • src/ApiLayer/Domains/Customers/CustomersService.php
    • src/ApiLayer/Domains/Customers/CustomersRoutes.php
    • src/ApiLayer/Domains/Customers/DTOs/ReqPoscliClientesDTO.php
    • src/ApiLayer/Domains/Customers/DTOs/ResPoscliClientesDTO.php
  4. Editamos el DTO de respuesta para definir los campos a mostrar:

    // src/ApiLayer/Domains/Customers/DTOs/ResPoscliClientesDTO.php
    public static $selectables = [
    'nombre',
    'apellidos',
    'email',
    'telefono',
    'direccion'
    ];

    public function toArray(): array
    {
    return [
    'id' => (string) $this->id,
    'fullName' => $this->nombre . ' ' . $this->apellidos,
    'email' => $this->email,
    'phone' => $this->telefono,
    'address' => $this->direccion
    ];
    }
  5. Editamos el DTO de petición para mapear los campos:

    // src/ApiLayer/Domains/Customers/DTOs/ReqPoscliClientesDTO.php
    protected $mapFilters = [
    'fullName' => 'nombre',
    'email' => 'email',
    'phone' => 'telefono',
    'address' => 'direccion'
    ];

    public function handle(array $data): InterfaceReqDto
    {
    // Separar el nombre completo en nombre y apellidos
    $fullNameParts = explode(' ', $data['fullName'] ?? '', 2);
    $this->nombre = $fullNameParts[0] ?? null;
    $this->apellidos = $fullNameParts[1] ?? null;

    $this->email = $data['email'] ?? null;
    $this->telefono = $data['phone'] ?? null;
    $this->direccion = $data['address'] ?? null;

    return $this;
    }
  6. Añadimos validaciones en el controlador:

    // src/ApiLayer/Domains/Customers/CustomersController.php
    $this->validations = [
    'headers' => ['x-tienda' => 'required|string'],
    'body' => [
    'fullName' => 'required|string',
    'email' => 'required|email',
    'phone' => 'required|string',
    'address' => 'string'
    ]
    ];
  7. ¡Y ya tenemos un CRUD completo para clientes!

Creación en un módulo específico

Si queremos crear el dominio dentro de un módulo (por ejemplo, en el módulo "Admin"), usamos:

php artesano create-domain Customer PPos_PoscliClientes Admin

Esto generará los archivos en src/ApiLayer/Modules/Admin/Domains/Customers/ y las rutas tendrán el prefijo admin/customers/.

Resumen

Las herramientas de generación de código del framework te permiten crear rápidamente:

  1. Infraestructuras Legacy: Para conectar con tablas de Quartup
  2. Dominios: CRUD completos con rutas, controladores, servicios y DTOs

Estos comandos aceleran enormemente el desarrollo, permitiéndote concentrarte en personalizar los DTOs y definir validaciones, mientras que el framework se encarga de todo el código repetitivo y estructural.

La combinación de estos dos comandos proporciona una forma poderosa y eficiente de construir APIs completas con un mínimo esfuerzo, siguiendo las mejores prácticas y manteniendo la coherencia en todo el proyecto.