Esta guía describe un enfoque minimalista para un sitio personal usando PHP puro: router simple, caché con sqlite y mínimos componentes externos para reducir mantenimiento.
Incluye ejemplos de código para el router, la regla de Apache (.htaccess), el script de cacheo y la tabla sqlite para reproducir el patrón.
Introducción
Para un sitio personal mayoritariamente estático, minimizar dependencias reduce complejidad operativa: menos builds, menos procesos a gestionar y actualizaciones centralizadas por el gestor de paquetes del sistema.
Prerrequisitos
Basado en la descripción original, los requisitos esenciales son:
- Servidor HTTP (Apache) con soporte para rewrite y uso de index.php como front controller.
- PHP instalado en el sistema y extensión pdo_sqlite para acceso a sqlite.
- Acceso para programar tareas (cron) si se usa un script que actualice la caché.
- Permisos de filesystem para que PHP lea/usen el directorio pages/ y escriba la base sqlite.
Desarrollo
La idea central es un front controller (index.php) que resuelve rutas estáticas buscando ficheros en pages/<path>/index.php o pages/<path>.php y que carga meta datos desde un array PHP.
Procedimiento
Flujo básico del router:
- Normalizar REQUEST_URI y eliminar query string.
- Componer rutas candidatas: pages/<path>/index.php y pages/<path>.php.
- Incluir el primer fichero existente dentro del layout principal o enviar 404 si no existe.
Ejemplo de router sencillo (54 líneas en la implementación original):
<?php
// Simple front controller: index.php
$uri = parse_url($_SERVER['REQUEST_URI'], PHP_URL_PATH);
$path = trim($uri, '/');
if ($path === '') {
$path = 'index';
}
$candidates = [
__DIR__ . '/pages/' . $path . '/index.php',
__DIR__ . '/pages/' . $path . '.php',
];
$found = null;
foreach ($candidates as $file) {
if (file_exists($file)) {
$found = $file;
break;
}
}
// Metadata map: ruta => título (ejemplo mínimo)
$meta = [
'index' => 'Inicio',
'music' => 'Música',
];
if ($found) {
$title = $meta[$path] ?? 'Página';
// variables disponibles para el layout
$contentFile = $found;
include __DIR__ . '/templates/layout.php';
exit;
}
http_response_code(404);
include __DIR__ . '/pages/404.php';
Lenguaje del código: PHP (php)
El layout (templates/layout.php) simplemente incluye el fichero de contenido dentro de la estructura HTML del sitio y usa $title para el <title>.
Ejemplos
A continuación se muestran fragmentos prácticos: la regla de Apache para ocultar index.php, la tabla sqlite, y un script cron que actualiza la caché.
Regla mínima en .htaccess para enviar todas las solicitudes a index.php salvo ficheros existentes:
RewriteEngine On
# Si el fichero o directorio existe, servirlo directamente
RewriteCond %{REQUEST_FILENAME} -f [OR]
RewriteCond %{REQUEST_FILENAME} -d
RewriteRule .* - [L]
# En caso contrario, reenviar a index.php
RewriteRule ^ index.php [L,QSA]
Lenguaje del código: texto plano (plaintext)
Ejemplo de esquema sqlite para almacenar elementos cacheados (tabla simple):
CREATE TABLE IF NOT EXISTS blog_cache (
id INTEGER PRIMARY KEY AUTOINCREMENT,
source TEXT NOT NULL,
title TEXT NOT NULL,
excerpt TEXT,
featured_image TEXT,
url TEXT NOT NULL,
fetched_at INTEGER NOT NULL
);
Lenguaje del código: SQL (Structured Query Language) (sql)
Script de ejemplo (cron) que ejecuta un script PHP para actualizar la caché desde fuentes externas:
# Entrar en /var/www/site y ejecutar el actor que actualiza sqlite
cd /var/www/site || exit 1
/usr/bin/php scripts/update_blog_cache.php
Lenguaje del código: Bash (bash)
Fragmento PHP que actualiza sqlite usando PDO: (ejemplo mínimo, adaptar parsing de cada fuente)
<?php
$db = new PDO('sqlite:' . __DIR__ . '/../data/blog_cache.sqlite3');
$db->setAttribute(PDO::ATTR_ERRMODE, PDO::ERRMODE_EXCEPTION);
// Ejemplo: array de fuentes (URLs) a procesar
$sources = [
'https://example.com/feed',
];
$stmt = $db->prepare('INSERT INTO blog_cache (source,title,excerpt,featured_image,url,fetched_at) VALUES (:source,:title,:excerpt,:image,:url,:ts)');
foreach ($sources as $src) {
// Simplificado: obtener HTML/JSON y extraer títulos; aquí se usa file_get_contents como ejemplo
$body = @file_get_contents($src);
if ($body === false) {
continue;
}
// Extraer ítems: esto depende del formato de la fuente. Aquí se asume extracción manual.
// Insertar un ejemplo ficticio de fila (reemplazar por parsing real)
$stmt->execute([
':source' => $src,
':title' => 'Título ejemplo',
':excerpt' => 'Extracto ejemplo',
':image' => '',
':url' => $src,
':ts' => time(),
]);
}
Lenguaje del código: PHP (php)
En la página que muestra la lista de blogs, lee la tabla blog_cache para renderizar los últimos registros en lugar de pedir cada feed en tiempo real.
Checklist
- Instalar PHP y habilitar pdo_sqlite desde el gestor de paquetes del sistema.
- Configurar Apache y añadir la regla .htaccess para el front controller.
- Crear estructura de carpetas: pages/, templates/, data/ y scripts/.
- Implementar el script cron para actualizar la caché sqlite y verificar permisos de escritura.
- Probar rutas estáticas y 404, revisar logs de Apache y PHP para errores.
Conclusión
Un sitio personal ligero implementado con PHP puro permite mantener control total sobre la superficie de mantenimiento al costo de escribir piezas pequeñas como el router y scripts de cacheo.
Esta aproximación favorece simplicidad operativa: menos dependencias, actualizaciones gestionadas por el sistema y procesos reducidos. Para sitios personales mayoritariamente estáticos, la diferencia frente a soluciones estáticas o frameworks pesados suele ser negligente en rendimiento y sustancial en simplicidad.
Si quieres, puedo adaptar los ejemplos para una estructura concreta de páginas, o convertir el router en una versión con logging y manejo básico de errores.

Deja un comentario