STO Online Store

UPF El Sabor de Birongo · Higuerote, Venezuela

STO

Online Store

Tienda + panel en un solo PHP

Cacao en grano · 1 kg

Bs 1.240,00

Bolivares

En stock: 42

AgregarDetalles

Bs 1.240,00

-15%

Chocolate artesanal 70%

Bs 980,50

Bolivares

En stock: 18

AgregarDetalles

Bs 980,50

-10%

Nibs de cacao · 250 g

Bs 640,00

Bolivares

En stock: 27

AgregarDetalles

Bs 640,00

-5%

Manteca de cacao

Bs 1.870,00

Bolivares

En stock: 9

AgregarDetalles

Bs 1.870,00

-20%

Cacao en polvo · 500 g

Bs 720,25

Bolivares

En stock: 34

AgregarDetalles

Bs 720,25

-8%

Bombones de licor

Bs 2.150,00

Bolivares

En stock: 6

AgregarDetalles

Bs 2.150,00

-12%

Tienda en línea y panel de gestión en un solo PHP: catálogo, carrito, pedidos e inventario para una empresa local de Higuerote.

E-commerce y gestión de inventario (web)2021MVC hecho a mano

Desarrollo full-stack: modelo de datos MySQL, backend PHP con patrón MVC propio, capa AJAX y toda la interfaz.

Arrastra la vitrina o pasa el cursor por encima para detenerla.

CatálogoBúsquedaCarritoFavoritosPedidosRegistro de pagoInventarioStock mínimoNotificacionesReportes PDFBitácora de visitasCatálogoBúsquedaCarritoFavoritosPedidosRegistro de pagoInventarioStock mínimoNotificacionesReportes PDFBitácora de visitas
01 / El encargo

Del cuaderno a la vitrina

Una unidad de producción familiar que vendía por catálogo informal necesitaba, a la vez, una tienda que mirara hacia afuera y un control que mirara hacia adentro.

El problema

Precios y stock en cuadernos

Una unidad de producción familiar en Higuerote vendía por catálogo informal: los precios y el stock vivían en cuadernos y mensajes sueltos, no había forma de que un cliente viera el inventario disponible ni de dejar un pedido registrado, y el control de qué se despachó, quién pagó y con qué referencia dependía de la memoria del encargado. Tampoco existía un reporte que permitiera cerrar el día o la semana.

La solución

Dos caras servidas por el mismo enrutador

Una aplicación PHP/MySQL de dos caras servida por el mismo enrutador. Hacia afuera, un escaparate con banner rotativo, catálogo paginado filtrable por categoría, buscador, ordenamiento por nombre o precio, ficha de producto con galería en lightbox, carrito y lista de favoritos. Hacia adentro, un dashboard con inventario, alertas de stock mínimo, alta de productos con portada y galería, gestión de clientes y administradores, pedidos pendientes y realizados, registro del medio de pago y su número de referencia, notificaciones, bitácora de últimas visitas y exportación de pedidos entregados a PDF por día, semana o mes.

Estado del repositorio

Proyecto publicado con licencia MIT en un único commit. Corre sobre un entorno LAMP local (`SERVERURL` apunta a `http://localhost/tienda/`). El snapshot publicado no incluye `controladores/pedidoControlador.php` ni `vistas/js/añadir.js` y `vistas/js/carrito.js`, referenciados por `ajax/pedidoAjax.php` y `vistas/inc/scripts.php`.

02 / El tamaño real

Lo que hay dentro del repositorio

105

archivos PHP en el repositorio

14.878

líneas de PHP

42

vistas de contenido en español

40

rutas en la lista blanca del router

12

controladores

11

endpoints AJAX

11

tablas MySQL

26

funciones en el modelo base

03 / Las piezas

Seis decisiones que sostienen las dos caras

Dos aplicaciones, un solo punto de entrada

`index.php` carga `vistas/plantilla.php`, que compara el primer segmento de la URL contra la constante `DASHBOARD` y decide si arma la tienda pública (header + vista + footer) o el panel (nav lateral fijo + navbar + vista), ramificando además según el cargo guardado en sesión.

Enrutado propio con lista blanca

El `.htaccess` reescribe cualquier ruta a `index.php?views=...`; `vistasControlador` la parte por `/` y `vistasModelo` la valida contra un arreglo de 40 vistas permitidas antes de tocar el disco. Todo lo que no esté en la lista cae en la vista 404.

Identificadores cifrados en la URL

`mainModel::encryption()` / `decryption()` cifran cada id con AES-256-CBC usando una clave `sha256(SECRET_KEY)` y un IV derivado de `SECRET_IV`, de modo que las URLs de detalle, edición y notificaciones nunca exponen el id numérico de la fila.

Formularios AJAX con confirmación

Cualquier `<form class="FormularioAjax">` es interceptado por `vistas/js/ajax.js`: lanza un diálogo SweetAlert2 cuyo texto depende del atributo `data-form` (save, update, delete, search), envía con `fetch` a un endpoint de `ajax/` y pinta la respuesta JSON del controlador sin recargar la página.

Reportes de pedidos en PDF

`dashboard-reportes.php` deja elegir Día, Semana o Mes y envía a `modelos/export.php`, que extiende FPDF para generar el «Reporte de Pedidos Entregados» con columnas de cliente, producto, cantidad, pago, tipo de pago, referencia y fecha, más numeración de páginas.

Notificaciones y bitácora de visitas

La tabla `notificaciones` guarda receptor, concepto, asunto y estado (`Sin leer`), y el header pinta un badge con el conteo en vivo; la tabla `visitas` registra cliente, estado y `ultima_visita`, que el panel lista paginada de cinco en cinco.

04 / La cara pública

El escaparate que ve el cliente

Banner rotativo, catálogo paginado con filtros y ordenamiento, y una ficha de producto con galería en lightbox. Todo servido por el mismo index.php.

http://localhost/tienda/
STO.
3521

Bienvenido a UPF El Sabor de Birongo

Cacao y derivados de Higuerote-Birongo. Compra en línea, paga y sigue tu pedido.

Nuestros servicios

Envío

Despacho a domicilio dentro de Higuerote y alrededores.

Inventario

Stock actualizado y alerta cuando baja del mínimo.

Tienda

Catálogo completo, favoritos y pedidos en línea.

Crea tu cuenta

REGISTRARME
UPF El Sabor de Birongo · VenezuelaHiguerote-Birongo · Bs

Inicio de la tienda

http://localhost/tienda/product/all/ASC/1/

Productos en tienda

Todos los productos habilitados y con existencia disponible en la tienda.

CATEGORÍAS BuscarOrdenar por
Resultados de la búsqueda: CACAOEliminar búsqueda

Cacao en grano · 1 kg

Bs 1.240,00

Bolivares

En stock: 42

AgregarDetalles

Chocolate artesanal 70%

Bs 980,50

Bolivares

En stock: 18

AgregarDetalles

Nibs de cacao · 250 g

Bs 640,00

Bolivares

En stock: 27

AgregarDetalles
Mostrando productos 1 al 10 de un total de 34
1234

Catálogo de productos

http://localhost/tienda/product-details/9f3a…c1b/

Detalles del producto

Volver

Cacao en grano · 1 kg

TipoMateria prima
Stock42 unidades
FabricanteUPF El Sabor
ModeloCriollo-Birongo

Descripción:

Grano fermentado y secado al sol en Birongo, seleccionado a mano y empacado en sacos de un kilo. Trazabilidad por lote y disponibilidad sujeta a la cosecha de la temporada.

Precio: Bs 1.240,00

Costo del envío: Bs 95,00

Cantidad1Agregar al carrito
Cantidad1Actualizar carrito

Galería de imágenes

Detalle de producto

El identificador del producto nunca viaja en claro: la URL lleva el token que devuelve mainModel::encryption(), y el controlador lo descifra antes de consultar.

05 / La cara privada

El backoffice que ve el encargado

La misma plantilla, otro layout: nav lateral de 300 px, navbar de 50 px y una rejilla de mosaicos con los conteos reales leídos de la base.

http://localhost/tienda/dashboard/

Arturo Sojo

Administrador

Inicio
Categorías
Clientes
Productos
Pedidos
Accesibilidad
Administradores
Configuraciones

Panel de control

¡Bienvenido ARTURO SOJO!

Categorías

8 Registradas

Clientes

46 Registrados

Productos

132 Registrados

Administradores

3 Registrados

Pedidos

57 Registrados

Dashboard del administrador

http://localhost/tienda/login/
Usuarioasojo
Contraseña••••••••
LOGIN

Login del panel

La frontera

El único momento oscuro

Toda la aplicación vive en gris muy claro con tarjetas blancas. El login es la excepción: un degradado violeta-noche a pantalla completa que marca visualmente dónde termina la tienda y dónde empieza el panel. Los errores no se pintan en el formulario, llegan como modales de SweetAlert2 disparados desde PHP.

AdministradorUsuarioadmin_security.phptoken de sesión

Las maquetas reproducen la interfaz real; los datos que muestran son de ejemplo.

06 / El recorrido

De la URL a la consulta

Siete escalones entre lo que escribe el navegador y lo que devuelve MySQL. Ninguno de ellos toca el disco antes de que la ruta pase por la lista blanca.

01.htaccess

Una sola RewriteRule con Options All -Indexes canaliza cualquier ruta hacia index.php?views=$1.

02index.php

Único punto de entrada: carga config/APP.php con las constantes de negocio y llama a vistasControlador.

03vistas/plantilla.php

Abre la sesión, parte la URL por «/» y compara el primer segmento contra la constante DASHBOARD.

04lista blanca

vistasModelo valida el nombre contra 40 rutas permitidas y comprueba con is_file() que la vista exista.

05controlador

12 controladores con 38 funciones; las escrituras entran por los 11 endpoints de ajax/ y devuelven JSON.

06mainModel

26 funciones compartidas: guardar, actualizar, eliminar, limpiar, validar, cifrar ids y paginar tablas.

07PDO · MySQL

Consultas preparadas sobre 11 tablas, con SQL_CALC_FOUND_ROWS y FOUND_ROWS() para el paginador.

Arquitectura completa

Patrón MVC artesanal de tres capas. `index.php` es el único punto de entrada: carga `config/APP.php` (constantes de negocio) y `vistasControlador`, que devuelve `vistas/plantilla.php`. La plantilla abre la sesión, parte `$_GET['views']` por `/` y, si el primer segmento coincide con la constante `DASHBOARD`, entra al panel; de lo contrario arma la web pública envolviendo la vista entre `header.php` y `footer.php`. La resolución de vistas pasa por `vistasModelo::obtener_vistas_modelo()`, que valida el nombre contra una lista blanca de 40 rutas y comprueba con `is_file()` que exista `vistas/contenidos/<lang>/<modulo>-<vista>.php`; cualquier otra cosa se resuelve como 404. Todos los controladores (12 archivos, 38 funciones) extienden `mainModel`, que centraliza en 26 funciones la conexión PDO, los helpers `guardar_datos`, `actualizar_datos`, `eliminar_registro` y `datos_tabla`, la limpieza de cadenas, la validación por expresiones regulares, el cifrado/descifrado de ids y el paginador de tablas. Las escrituras no viajan por formularios tradicionales sino por los 11 endpoints de `ajax/`, cada uno un despachador que instancia su controlador y ejecuta la acción indicada en un campo `modulo_*` del POST, devolviendo JSON que `ajax.js` convierte en un modal de SweetAlert2. Los listados se generan en el servidor: los controladores construyen el HTML de tarjetas y tablas como string y lo devuelven a la vista, apoyándose en `SQL_CALC_FOUND_ROWS` + `FOUND_ROWS()` para paginar. Deuda técnica visible en el código: las contraseñas se guardan con el mismo cifrado reversible `encryption()` en lugar de un hash unidireccional, y varios paginadores interpolan variables ya saneadas directamente en la consulta en vez de enlazarlas.

07 / Funcionalidades

El mosaico completo

Los mismos mosaicos cuadrados del panel, uno por funcionalidad. Al pasar el cursor se rellenan de rojo, igual que el elemento activo del menú lateral.

01

Catálogo público paginado de 10 productos por página, filtrable por categoría habilitada y ordenable A-Z, Z-A, precio menor a mayor y precio mayor a menor.

02

Buscador de productos en modal que persiste el término en sesión (`busqueda_tienda`) y se limpia con un botón dedicado.

03

Ficha de producto con portada, tipo, stock, fabricante, modelo, descripción, precio con descuento aplicado, costo de envío y galería de imágenes en lightbox (fslightbox).

04

Carrito de compras por cliente con alta, actualización de cantidad y eliminación por AJAX, y contador en el header.

05

Lista de favoritos por cliente con su propio contador y paginador.

06

Registro y autenticación de clientes y de personal, con estado de cuenta (`Activa`) y token de sesión generado en el login.

07

Dos roles diferenciados: `Administrador` (categorías, administradores, empresa, alta de productos) y `Usuario`, con menús y vistas condicionadas.

08

Inventario con alta, edición, borrado, portada, galería y ficha de información por producto, incluyendo código de barras y SKU.

09

Vista de productos en stock mínimo, apoyada en los campos `producto_stock` y `producto_stock_minimo`.

10

Gestión de pedidos separada en pendientes y realizados, con búsqueda y ficha de detalle.

11

Registro del pago de un pedido: medio de pago y número de referencia, guardados por AJAX.

12

Exportación a PDF de los pedidos entregados por día, semana o mes.

13

Formulario de contacto que arma y envía el correo desde `correoControlador` con validación por expresiones regulares.

14

Ficha de empresa editable desde el panel y datos de contacto, país, dirección, teléfono y redes sociales centralizados en `config/APP.php`.

15

Selector de avatar entre 12 imágenes incluidas (variantes femeninas, masculinas y dos por defecto).

16

Configuración de negocio por constantes: símbolo y nombre de moneda, decimales, separadores, 7 tipos de documento de usuario, 7 de empresa, 14 unidades de producto y límites de peso para portada (3 MB) y galería (7 MB).

17

Scripts de respaldo e importación de la base de datos vía `mysqldump` / `mysql` desde `modelos/respaldar.php` e `import.php`.

18

Estructura multiidioma por carpeta (`vistas/contenidos/es/`, `vistas/inc/es/`) gobernada por la constante `LANG`.

08 / Stack

Con qué está hecho

Sin framework, sin gestor de dependencias: cada librería está copiada dentro del repositorio.

01

Backend

PHP (sin framework)MVC propio: controladores / modelos / vistasPDO con consultas preparadasSesiones PHPopenssl AES-256-CBC para cifrado de ids
02

Base de datos

MySQL / MariaDBEsquema de 11 tablas (`DataBase/sto.sql`)mysqldump y mysql CLI para respaldo e importación
03

Front-end

HTML5 + CSS3 propio (`vistas/css/style.css`)MDBootstrap 5Bootstrap bundleNormalize.css 8.0.1Font Awesome 5.15.1Fuentes web propias: Roboto Condensed, Roboto Medium y Poppins
04

JavaScript

JavaScript nativo con Fetch APIjQuery 3.6.0SweetAlert2fslightboxJsBarcode (incluido en `vistas/js/`)
05

Reportes y servidor

FPDF (`modelos/fpdf.php`)Apache con mod_rewrite (`.htaccess`)
09 / Retos

Lo que costó resolver

Seis problemas concretos del código y la decisión que los cerró. Toca cada uno para abrirlo.

Solución

Un único `plantilla.php` decide por el primer segmento de la URL contra la constante `DASHBOARD` y, dentro del panel, vuelve a ramificar por `$_SESSION['cargo_sto']`: el administrador recibe `nav_lateral.php` + `nav_bar.php`, mientras que el rol `Usuario` reutiliza el header y el footer de la tienda.

Solución

Una sola `RewriteRule` en `.htaccess` canaliza todo hacia `index.php?views=$1` con `Options All -Indexes`; luego `vistasModelo` valida el nombre contra una lista blanca de 40 vistas y solo después compone la ruta del archivo, devolviendo 404 ante cualquier valor no previsto.

Solución

`encryption()` cifra cada id con AES-256-CBC (clave `sha256(SECRET_KEY)`, IV de 16 bytes derivado de `SECRET_IV`) y `datos_tabla()` lo descifra y sanea antes de consultar, de modo que la URL viaja siempre con un token opaco.

Solución

Una convención de una sola clase: cualquier formulario marcado como `FormularioAjax` es capturado por `ajax.js`, que arma un `FormData`, pide confirmación con SweetAlert2 —con el texto adaptado al `data-form` y al `data-lang`— y envía con `fetch` al endpoint de `ajax/`, mostrando la respuesta JSON sin salir de la vista.

Solución

`cliente_paginador_producto_controlador()` valida el orden contra la lista `[ASC, DESC, MAX, MIN]`, comprueba que la categoría exista y esté habilitada, traduce MAX/MIN a orden por `producto_precio_venta` y calcula el total con `SQL_CALC_FOUND_ROWS` en la misma consulta que trae la página, mostrando siempre solo productos habilitados con stock mayor que cero.

Solución

El pedido guarda medio de pago y número de referencia desde `dashboard-pedido-pay.php`, y `modelos/export.php` extiende FPDF con una cabecera de siete columnas para emitir el reporte de pedidos entregados del día, la semana o el mes en un clic.

E-commerce y gestión de inventario (web)2021

STO Online Store

STO es una tienda en línea completa escrita en PHP plano sobre una arquitectura MVC hecha a mano: un único `index.php` levanta la plantilla y, según el primer segmento de la URL, sirve la tienda pública o el dashboard privado.

El repositorio está configurado para un cliente real: la constante `COMPANY` es «UPF El Sabor de Birongo», el país es Venezuela, la dirección «Higuerote-Birongo» y la moneda son bolívares con símbolo «Bs».

Cubre el ciclo comercial completo: catálogo con categorías, búsqueda y ordenamiento, ficha de producto con galería, carrito, favoritos, pedidos con registro de pago, notificaciones al cliente y reportes en PDF.

El backoffice maneja dos roles (`Administrador` y `Usuario`) que comparten plantilla pero reciben menús, vistas y permisos distintos; la seguridad de cada pantalla del panel se refuerza con el include `vistas/inc/admin_security.php`.

Todo el proyecto está internacionalizado por carpeta de idioma (`vistas/contenidos/<lang>/`) y la constante `LANG`, aunque el snapshot solo incluye el paquete `es`.

El repositorio se publicó en GitHub el 10 de enero de 2025 en un solo commit; la licencia MIT y la clave `SECRET_KEY = '$STO@2021'` en `config/SERVER.php` sitúan el desarrollo en 2021.

Comercio serio y ordenado: azul marino de administración, azul enlace para el precio y un rojo coral que marca lo activo. Grises muy claros, tarjetas blancas con esquinas de 10 px y sombra suave; el único momento oscuro es el degradado violeta-noche del login, que separa visualmente la tienda del panel.

STO Online Store

¿Quieres algo así para tu producto?

Una tienda y un panel completos sobre PHP plano: enrutado propio con lista blanca, ids cifrados en la URL, escrituras por AJAX y reportes en PDF. Si necesitas algo así —o migrarlo a algo moderno sin perder el negocio que ya funciona— es terreno conocido.