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.
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).
woocommerce_cart_updated).artisan bridge:dispatch (local o vía SSH).Comando CLI
wp laravel:call
Función helper (PHP)
function wp_laravel_call(string $action, array $data, int $user_id = null): array;
Internamente
proc_open() para ejecutar artisan.escapeshellarg().Uso
php artisan bridge:dispatch
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
echo json_encode($result);fwrite(STDERR, json_encode($error)); exit(1);| 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. |
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()];
}
}
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.
proc_open() habilitado.proc_open() por cola asíncrona (Redis, DB).bridge.log).request_id en el payload.shell_exec() sin sanitización.bridge:dispatch a HTTP.Este patrón es de dominio público.
Los componentes de código pueden distribuirse bajo MIT/GPL según el proyecto.
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.