Benjamín Sánchez Cárdenas
Equipo BDS


Interface WP ⇄ Laravel

Patrón de integración para entornos autohospedados mediante CLI

Versión: 1.0
Fecha: 2025-04-05


Prólogo

Esta arquitectura fue originalmente concebida, propuesta e implementada por el autor en el Sistema de Votaciones Online del Poder Judicial de Chile (PJUD), específicamente para el Área de Bienestar, con el objetivo de garantizar integridad, trazabilidad y seguridad en procesos electorales internos.

En dicho entorno —una intranet controlada, sin exposición a internet y con servidores dedicados— se descartó la comunicación vía APIs REST por considerarla innecesariamente compleja, con mayor superficie de ataque y dependiente de mecanismos de autenticación frágiles. En su lugar, se diseñó un canal de comunicación directo entre WordPress (frontend y autenticación) y Laravel (lógica de negocio), utilizando exclusivamente comandos CLI y el protocolo SSH como transporte cifrado.

El éxito operativo, la estabilidad y la facilidad de auditoría de dicha implementación validaron el enfoque. Hoy, este patrón se propone como solución genérica para cualquier integración entre WordPress y Laravel en entornos autohospedados donde el control total del sistema, la simplicidad y la seguridad son prioritarios.

— Benjamín Sánchez Cárdenas, Equipo BDS

Objetivo

Permitir la comunicación segura, eficiente y extensible entre WordPress (frontend, autenticación, UX) y Laravel (lógica de negocio, modelos, procesamiento) en entornos autohospedados, sin exponer APIs HTTP, usando exclusivamente comandos CLI (wp-cli + artisan) y canales IPC (stdin/stdout o SSH).

Alcance

Arquitectura

+----------------+ CLI Call +------------------+ | | ---------------------> | | | WordPress | (wp-cli → artisan) | Laravel | | (Frontend) | <--------------------- | (Business Logic) | | | JSON via stdout | | +----------------+ +------------------+

Flujo de ejecución

  1. WordPress dispara un hook (ej. woocommerce_cart_updated).
  2. Plugin de WordPress ejecuta un comando wp-cli personalizado.
  3. wp-cli llama a artisan bridge:dispatch (local o vía SSH).
  4. Laravel ejecuta la acción registrada, procesa y devuelve JSON por stdout.
  5. WordPress recibe la respuesta y actúa (mostrar mensaje, log, etc.).

Componentes

1. WordPress: Plugin wp-laravel-bridge

Comando CLI
wp laravel:call --user= --data=

Función helper (PHP)

function wp_laravel_call(string $action, array $data, int $user_id = null): array;

Internamente

2. Laravel: Comando bridge:dispatch

Uso
php artisan bridge:dispatch --user= --payload=

Registro de acciones (routes/bridge.php)

return [
    'cart.sync'        => \App\Actions\SyncCart::class,
    'vote.register'    => \App\Actions\RegisterVote::class,
    'course.enroll'    => \App\Actions\EnrollInCourse::class,
    // ...
];

Contrato de acción

interface BridgeAction
{
    public function handle(array $data): array;
}

Salida

Seguridad

Medida Implementación
Autenticación El user_id lo provee WordPress (sesión validada). Laravel confía en él.
Validación Cada acción valida entrada con Laravel Validator o clases propias.
Ejecución Solo comandos CLI permitidos. Nada de eval() ni ejecución dinámica.
Red Si es remoto, solo vía SSH con clave pública y ForceCommand.
Permisos Usuario del servidor (www-data) con acceso mínimo a rutas de Laravel/WordPress.

Ejemplo: Sincronización de carrito (WooCommerce)

WordPress (plugin)

add_action('woocommerce_cart_updated', function() {
    if (!is_user_logged_in()) return;
    
    $items = array_column(WC()->cart->get_cart(), 'product_id');
    $result = wp_laravel_call('cart.sync', [
        'items' => $items,
        'total' => WC()->cart->get_total('numeric')
    ]);
    
    if ($result['success'] ?? false) {
        WC()->session->set('cart_tracked', true);
    }
});

Laravel (SyncCart.php)

class SyncCart implements BridgeAction
{
    public function handle(array $data): array
    {
        CartTracker::updateOrCreate(
            ['user_id' => $data['user_id']],
            ['items' => $data['items'], 'total' => $data['total']]
        );
        return ['success' => true, 'tracked_at' => now()];
    }
}

Comunicación bidireccional (opcional)

Para notificaciones Laravel → WordPress:

// En Laravel
shell_exec("wp --path=/var/www/wordpress user meta set {$userId} last_action " . time());
Requiere que Laravel pueda ejecutar wp-cli.

Requisitos del sistema

Escalabilidad

Anti-patrones a evitar

Estructura de archivos sugerida

wordpress/ └── wp-content/plugins/wp-laravel-bridge/ ├── wp-laravel-bridge.php └── cli/class-laravel-command.php laravel/ ├── app/Actions/ │ ├── SyncCart.php │ └── ... ├── routes/bridge.php └── app/Console/Commands/BridgeDispatch.php

Licencia

Este patrón es de dominio público.
Los componentes de código pueden distribuirse bajo MIT/GPL según el proyecto.

Nota final

Esta interface no es una solución universal, sino una herramienta para entornos controlados donde la simplicidad, seguridad y control del sistema son prioritarios sobre la portabilidad.

— Benjamín Sánchez Cárdenas, Equipo BDS