phview / framework
Declarative Server-Side Rendering (SSR) engine in PHP with native Alpine.js integration
Requires
- php: >=8.0
- vlucas/phpdotenv: ^5.6
Requires (Dev)
None
Suggests
None
Provides
None
Conflicts
None
Replaces
None
README
PhView es un framework micro y motor de renderizado declarativo Server-Side en PHP, diseñado para ofrecer una experiencia de desarrollo fluida (estilo SwiftUI o Vue.js) combinada con la reactividad ligera de Alpine.js en el frontend.
Permite construir aplicaciones web modernas, modulares y de alto rendimiento sin depender de compiladores complejos (como Webpack o Vite) ni sobrecargar el navegador con JavaScript innecesario.
🌟 Características Principales
- Arquitectura Declarativa: Componentes PHP con interfaz fluida (method chaining) y método
content(). - Estructura por Características (Feature-Based): Organiza tus controladores, vistas y lógica en subcarpetas independientes (
features/home,features/auth,features/dashboard). - Descubrimiento Automático de Controladores: Registro automático de rutas mediante
ControllerInterface. - Filtro Híbrido de Plantillas: Ignora automáticamente archivos de renderizado plano (
.template.php,.tpl.phpo dentro de carpetas/templates/) durante la autocarga para ser llamados únicamente bajo demanda medianteinclude. - Enrutado RESTful: Soporte nativo para verbos HTTP (
GET,POST,PUT,PATCH,DELETE,OPTIONS,HEAD) y parámetros dinámicos en la URL (/store/{id}/article). - Inyección Única de Scripts (
staticContent): Evita la duplicación de código CSS/JS inyectando los assets de un componente una sola vez en el<head>del layout global. - Cliente HTTP Integrado (
Fetch): Utilidad tipo Axios para realizar peticiones Backend-to-Backend con gestión automática de tokens, JSON y respuestas normalizadas. - Soporte para
.env: Carga transparente de variables de entorno mediantevlucas/phpdotenv.
📁 Estructura del Proyecto
phview/
├── src/ # LIBRERÍA CORE (Agnóstica y Reutilizable)
│ ├── App.php # Orquestador y ciclo de vida global
│ ├── Component.php # Clase base abstracta de componentes
│ ├── ControllerInterface.php # Interfaz para autorregistro de rutas
│ ├── Routing.php # Motor de enrutamiento RESTful
│ └── Support/
│ └── Fetch.php # Cliente HTTP Backend-to-Backend
│
├── example/ # APLICACIÓN DE EJEMPLO
│ ├── app/
│ │ ├── MainApp.php # Layout HTML Base de la App
│ │ └── features/ # Organización por módulos / características
│ │ ├── home/
│ │ │ ├── HomeController.php
│ │ │ └── HomeView.php
│ │ └── auth/
│ │ ├── AuthController.php
│ │ ├── LoginView.php
│ │ └── register.template.php # Plantilla plana ignorada por autocarga
│ └── public/ # Raíz pública del servidor (Document Root)
│ ├── .htaccess # Front Controller (Redirección a index.php)
│ └── index.php # Punto de entrada (Front Controller)
│
├── composer.json # Autoloading PSR-4
└── README.md
🚀 Instalación y Configuración
1. Instalación vía Composer
Asegúrate de tener configurado tu composer.json con el autoloader PSR-4:
{
"name": "tu-usuario/phview",
"type": "library",
"autoload": {
"psr-4": {
"PhView\\": "src/",
"App\\": "example/app/"
}
},
"require": {
"php": ">=8.0",
"vlucas/phpdotenv": "^5.6"
}
}
Ejecuta el autoloader:
composer dump-autoload
2. Punto de Entrada (public/index.php)
Tu archivo index.php solo requiere cargar el autoloader e iniciar la aplicación:
<?php require_once __DIR__ . '/../../vendor/autoload.php'; use App\MainApp; // Arranca PhView escaneando controladores en app/ y define la ruta base de la URL MainApp::run( baseDir: __DIR__ . '/../app', basePath: '/phview/example/public' // Omite o pasa null si estás en un dominio directo o VPS );
🛠️ Uso del Framework
1. Definir el Layout Base (MainApp.php)
Extiende de PhView\App para establecer la plantilla HTML global. Aquí es donde se compilan automáticamente los scripts y estilos declarados en los staticContent() de tus componentes.
namespace App; use PhView\App; class MainApp extends App { protected static function renderLayout(string $content): string { $registeredStatics = static::renderCollectedStaticContent(); return <<<HTML <!DOCTYPE html> <html lang="es"> <head> <meta charset="UTF-8"> <meta name="viewport" content="width=device-width, initial-scale=1.0"> <title>Mi Aplicación PhView</title> <script defer src="https://cdn.jsdelivr.net/npm/alpinejs@3.x.x/dist/cdn.min.js"></script> <script src="https://cdn.tailwindcss.com"></script> <!-- Inyección de assets estáticos de todos los componentes usados --> {$registeredStatics} </head> <body class="bg-gray-900 text-white font-sans"> {$content} </body> </html> HTML; } }
2. Crear Componentes (Component)
Hereda de PhView\Component. Si tu componente requiere CSS o JS propio que solo deba cargarse una vez en la página (sin importar cuántas instancias del componente existan), colócalo en staticContent().
namespace App\features\ui; use PhView\Component; class CustomInput extends Component { private string $name; private string $label; public function __construct(string $name, string $label) { $this->name = $name; $this->label = $label; } public static function staticContent(): string { return <<<HTML <style> .custom-input { transition: all 0.2s ease-in-out; } </style> HTML; } public function content(): string { return <<<HTML <div class="flex flex-col gap-1 mb-4" x-data="{ focus: false }"> <label class="text-sm font-semibold text-gray-400">{$this->label}</label> <input name="{$this->name}" @focus="focus = true" @blur="focus = false" :class="{ 'border-purple-500 shadow-lg': focus }" class="custom-input bg-gray-800 border border-gray-700 rounded-lg p-2 text-white outline-none" /> </div> HTML; } }
3. Crear Controladores (ControllerInterface) y Renderizar Vistas
Implementa ControllerInterface en tus controladores dentro de cualquier subdirectorio de app/. PhView los descubrirá y registrará sus rutas automáticamente al arrancar.
Puedes retornar tanto instancias de clases Component como incluir plantillas HTML/PHP planas (.template.php / .tpl.php):
namespace App\features\auth; use PhView\ControllerInterface; use PhView\Routing; class AuthController implements ControllerInterface { public static function registerRoutes(): void { // 1. Renderizado mediante Clase Component Routing::Route('GET', '/login', fn() => new LoginView()); // 2. Renderizado mediante Plantilla Plana (.template.php) Routing::Route('GET', '/register', function() { include __DIR__ . '/register.template.php'; }); } }
🎨 Sistema de Plantillas Híbrido
PhView permite combinar el renderizado de componentes POO (Component) con archivos de plantillas PHP nativos y simples (include).
Para evitar que el escáner del motor ejecute prematuramente archivos de maquetación pura durante el arranque de controladores, el núcleo de PhView ignora automáticamente los archivos que cumplas con cualquiera de estas condiciones:
- Terminan en
.template.php(ej.register.template.php). - Terminan en
.tpl.php(ej.register.tpl.php). - Se encuentran dentro de una subcarpeta llamada
/templates/(ej.features/auth/templates/register.php).
De esta manera, puedes colocar tus plantillas directamente en la carpeta de la característica correspondiente (features/auth/) sin interferir con la autocarga de controladores.
📡 Utilidad Fetch (Cliente HTTP)
PhView\Support\Fetch es una utilidad estática inspirada en Axios y Fetch API, diseñada para facilitar la comunicación Backend-to-Backend o consumir APIs externas/internas de forma expresiva y segura.
Características de Fetch:
- Soporta todos los verbos HTTP:
get(),post(),put(),patch(),delete(),head(),options(). - Inyección automática del Token Bearer desde
$_SESSION['token']o explícitamente. - Soporte para Basic Auth y API Keys personalizadas.
- Respuesta estructurada y normalizada con código de estado HTTP y bandera
ok.
Ejemplos de Uso
1. Petición GET con Autenticación de Sesión
use PhView\Support\Fetch; // Inyecta automáticamente $_SESSION['token'] en las cabeceras $response = Fetch::get('/user/profile', auth: true); if ($response['ok']) { $userData = $response['data']; echo "Bienvenido, " . $userData['name']; }
2. Petición POST creando datos (JSON Payload)
$response = Fetch::post('/products', [ 'title' => 'Laptop Gaming', 'price' => 1200.00 ], auth: true); if ($response['status'] === 201) { // Producto creado exitosamente }
3. Autenticación Basic Auth (Microservicios)
$response = Fetch::get('https://api.externa.com/v1/status', auth: [ 'user' => 'admin_user', 'pass' => 'super_password' ]);
4. API Keys Personalizadas
$response = Fetch::get('/analytics/data', auth: [ 'key_name' => 'X-API-Key', 'value' => 'tu_api_key_secreta' ]);
5. Estructura del Valor de Retorno
Todas las peticiones devuelven un arreglo asociativo consistente:
[
'status' => 200, // Código HTTP (200, 201, 404, 500, etc.)
'ok' => true, // Boolean: true si el código está entre 200 y 299
'data' => [...] // Arreglo decodificado desde JSON o string con la respuesta cruda
]
📄 Licencia
Este proyecto está bajo la Licencia MIT. Eres libre de usarlo, modificarlo y distribuirlo en proyectos personales o comerciales.