El Profe Arci – Mtro. Fernando Arciniega –

Crea un carrito de compras con PHP, MySQL y Bootstrap

Publicado el 28 noviembre, 2024
por Mtro. Fernando Omar Arciniega Martínez

Crea un carrito de compras con PHP, MySQL y Bootstrap

Cómo crear una tienda en línea paso a paso: guía completa para estudiantes (Frontend y Backend)

En esta guía detallada, te explico cómo construir una tienda en línea paso a paso utilizando PHP, MySQL y Bootstrap. Incluye tanto la interfaz de usuario (frontend) como la interfaz de administración (backend). Es importante seguir cada paso cuidadosamente y mantener la estructura de archivos organizada.

PHP es un lenguaje de programación del lado del servidor ampliamente utilizado para desarrollar aplicaciones web dinámicas e interactivas. Es conocido por su facilidad de uso, integración con bases de datos y flexibilidad, lo que lo hace ideal para gestionar formularios, sesiones de usuarios y otros elementos de sitios web.

MySQL es un sistema de gestión de bases de datos relacional que permite almacenar, organizar y recuperar grandes cantidades de datos de forma eficiente. Se utiliza en conjunto con lenguajes como PHP para crear aplicaciones web que requieren almacenamiento y manejo de datos, como tiendas en línea, foros y sistemas de gestión de contenido.

Bootstrap es un framework de código abierto para el desarrollo de interfaces de usuario responsivas y móviles en la web. Facilita la creación de páginas y aplicaciones con un diseño atractivo, gracias a su conjunto de componentes prediseñados y sus sistemas de grillas flexibles, haciendo que el desarrollo sea más rápido y uniforme.

Requisitos previos:

  • Conocimientos básicos de PHP y MySQL.
  • Servidor local como XAMPP o WAMP.

Paso 1: Crear la estructura de carpetas y archivos

Crea la siguiente estructura de carpetas y archivos en tu proyecto. Debes guardar tus archivos en la carpeta de “localhost”, por ejemplo, si tienes instalado Xampp, la ruta es: C:\xampp\htdocs y dentro de esta carpeta debe estar “tienda-en-línea“, en el navegador lo probarás como: http://localhots/tienda-en-linea.

tienda-en-linea/
│
├── incluir/
│   ├── conexion.php
│   ├── encabezado.php
│   └── pie.php
│
├── recursos/
│   └── imagenes/
│
├── admin
│   ├── inicio_sesion.php        . . . (backend)
│   ├── panel_control.php        . . . (backend)
│   ├── gestion_productos.php    . . . (backend)
│   ├── agregar_producto.php     . . . (backend)
│   └── editar_producto.php      . . . (backend)
│   └── cerrar_sesion.php        . . . (backend)
│
├── index.php              . . . (frontend)
├── carrito.php            . . . (frontend)
├── pago.php               . . . (frontend)
└── pago_exitoso.php       . . . (frontend)

Paso 2: Configurar la base de datos

  1. Crea la base de datos en MySQL llamada comercio_electronico e inserta un usuario de ejemplo:
CREATE DATABASE comercio_electronico;
USE comercio_electronico;

CREATE TABLE productos (
    id_producto INT AUTO_INCREMENT PRIMARY KEY,
    nombre VARCHAR(100) NOT NULL,
    descripcion TEXT,
    precio DECIMAL(10, 2) NOT NULL,
    imagen VARCHAR(255),
    stock INT NOT NULL DEFAULT 0
);

CREATE TABLE usuarios (
    id_usuario INT AUTO_INCREMENT PRIMARY KEY,
    usuario VARCHAR(50) UNIQUE NOT NULL,
    password VARCHAR(255) NOT NULL
);

-- Insertar un usuario de ejemplo
INSERT INTO usuarios (usuario, password) VALUES ('administrador', '12345');

Paso 3: Crear la conexión a la base de datos

Crea el archivo incluir/conexion.php:

<?php
// Datos de conexión a la base de datos
$host = "localhost";
$usuario = "root"; // Cambia esto por tu nombre de usuario de MySQL, si es diferente
$password = ""; // Cambia esto por tu contraseña de MySQL si tienes una
$base_de_datos = "comercio_electronico";

// Crear la conexión
$conexion = new mysqli($host, $usuario, $password, $base_de_datos);

// Verificar la conexión
if ($conexion->connect_error) {
    die("Error de conexión: " . $conexion->connect_error);
} else {
    echo "";
}

// Establecer el conjunto de caracteres a UTF-8
$conexion->set_charset("utf8");
?>

Paso 4: Crear el encabezado y pie de página

En esta sección se diseñó el logotipo, el nombre de la tienda y el menú con el siguiente código:

Archivo incluir/encabezado.php

<!DOCTYPE html>
<html lang="es">
<head>
    <meta charset="UTF-8">
    <meta name="viewport" content="width=device-width, initial-scale=1.0">
    <title>Tienda en Línea</title>
    <link rel="stylesheet" href="https://stackpath.bootstrapcdn.com/bootstrap/4.5.2/css/bootstrap.min.css">
</head>
<body>
    <nav class="navbar navbar-expand-lg navbar-light bg-light">
        <a class="navbar-brand" href="index.php">
            <img src="https://getbootstrap.com/docs/4.5/assets/brand/bootstrap-solid.svg" width="30" height="30" alt="Logo de Bootstrap" class="d-inline-block align-top">
            Tienda en Línea
        </a>
        <button class="navbar-toggler" type="button" data-toggle="collapse" data-target="#navbarNav" aria-controls="navbarNav" aria-expanded="false" aria-label="Toggle navigation">
            <span class="navbar-toggler-icon"></span>
        </button>
        <div class="collapse navbar-collapse" id="navbarNav">
            <ul class="navbar-nav ml-auto">
                <li class="nav-item">
                    <a class="nav-link" href="index.php">Inicio</a>
                </li>
                <li class="nav-item">
                    <a class="nav-link" href="carrito.php">Carrito</a>
                </li>
                <li class="nav-item">
                    <a class="nav-link" href="pago.php">Pagar</a>
                </li>
            </ul>
        </div>
    </nav>

Este código es una estructura básica de una página web en HTML con Bootstrap para darle estilo y funcionalidad:

  1. Estructura HTML:
    • Define la estructura básica de la página con elementos como <!DOCTYPE html>, <html>, <head>, y <body>.
    • Meta y Título: El <meta charset="UTF-8"> define la codificación de caracteres como UTF-8 para acentos y el lenguaje español.
    • <meta name="viewport" content="width=device-width, initial-scale=1.0"> asegura que el sitio se vea bien en dispositivos móviles.
    • <title> define el título de la página.
  2. Enlaces a CSS: Se incluyen un archivo de estilos CSS de Bootstrap para usar componentes prediseñados.
  3. Barra de navegación:
  • <nav>: Contiene la barra de navegación.
  • Logo y enlace: Un logo de Bootstrap es mostrado con <img>.
  • Botón de menú colapsable: Permite que el menú se colapse en dispositivos móviles.
  • Enlaces de navegación: <ul> con <li> que dirigen a diferentes páginas (inicio.php, carrito.php, pago.php).

El uso de Bootstrap proporciona un diseño responsivo y una presentación uniforme.


Archivo incluir/pie.php

Al visualizar este archivo de manera individual, no se ver+an los estilos, ya que están siendo llamados desde el archivo index.php

    <footer class="bg-dark text-white text-center py-3 mt-5">
        <div class="container">
            <p class="mb-1">&copy; <?php echo date("Y"); ?> Tienda en Línea. Todos los derechos reservados.</p>
            <div class="d-flex justify-content-center">
                <a href="https://www.facebook.com" target="_blank" class="text-white mx-2">
                    <i class="bi bi-facebook" style="font-size: 1.5rem;"></i>
                </a>
                <a href="https://www.twitter.com" target="_blank" class="text-white mx-2">
                    <i class="bi bi-twitter" style="font-size: 1.5rem;"></i>
                </a>
                <a href="https://www.instagram.com" target="_blank" class="text-white mx-2">
                    <i class="bi bi-instagram" style="font-size: 1.5rem;"></i>
                </a>
            </div>
        </div>
    </footer>
</body>
</html>

<!-- Agregar enlace a Bootstrap Icons -->
<link rel="stylesheet" href="https://cdn.jsdelivr.net/npm/bootstrap-icons/font/bootstrap-icons.css">

Creación del Frontend para la tienda en linea

Paso 5: Crear la interfaz de usuario

Archivo index.php (Página de inicio):

<?php
// Incluir la conexión a la base de datos
include 'incluir/conexion.php';
?>

<!DOCTYPE html>
<html lang="es">
<head>
    <meta charset="UTF-8">
    <meta name="viewport" content="width=device-width, initial-scale=1.0">
    <title>Inicio - Tienda en Línea</title>
    <link rel="stylesheet" href="https://stackpath.bootstrapcdn.com/bootstrap/4.5.2/css/bootstrap.min.css">
</head>
<body>
    <?php include 'incluir/encabezado.php'; ?>

    <div class="container mt-5">
        <h1 class="text-center">Bienvenido a nuestra tienda en línea</h1>
        <div class="row">
            <?php
            // Consultar productos de la base de datos
            $consulta = "SELECT * FROM productos";
            $resultado = $conexion->query($consulta);

            if ($resultado->num_rows > 0) {
                while ($producto = $resultado->fetch_assoc()) {
                    // Concatenar la ruta de la carpeta con el nombre del archivo
                    $ruta_imagen = 'recursos/imagenes/' . $producto['imagen'];

                    echo '
                    <div class="col-md-4 mb-4">
                        <div class="card">
                            <a href="' . $ruta_imagen . '" target="_blank">
                                <div class="card-img-top" style="height: 200px; overflow: hidden;">
                                    <img src="' . $ruta_imagen . '" class="img-fluid" alt="' . $producto['nombre'] . '" style="width: 100%; object-fit: cover; height: 100%;">
                                </div>
                            </a>
                            <div class="card-body">
                                <h5 class="card-title">' . $producto['nombre'] . '</h5>
                                <p class="card-text">' . $producto['descripcion'] . '</p>
                                <p class="card-text"><strong>Precio: $' . number_format($producto['precio'], 2) . '</strong></p>
                                <a href="carrito.php?accion=agregar&id=' . $producto['id_producto'] . '" class="btn btn-primary">Agregar al carrito</a>
                            </div>
                        </div>
                    </div>
                    ';
                }
            } else {
                echo '<p class="text-center">No hay productos disponibles en este momento.</p>';
            }
            ?>
        </div>
    </div>

    <?php include 'incluir/pie.php'; ?>

    <script src="https://code.jquery.com/jquery-3.5.1.slim.min.js"></script>
    <script src="https://cdn.jsdelivr.net/npm/@popperjs/core@2.9.2/dist/umd/popper.min.js"></script>
    <script src="https://stackpath.bootstrapcdn.com/bootstrap/4.5.2/js/bootstrap.min.js"></script>
</body>
</html>

Hasta este punto, tu tienda deberá tener la siguiente apariencia:

Nota: no debe mostrar ningun tipo de error, ya que el mensaje de “No hay productos disponibles en este momento” hace una conexión a la base de datos y verifica si hay registros en la tabla productos


Archivo carrito.php (Carrito de compras):

Este archivo es un script PHP para gestionar un carrito de compras de la tienda en línea.

  1. Conexión a la base de datos: Incluye un archivo externo (incluir/conexion.php) que establece la conexión con la base de datos.
  2. Gestión de la sesión: Inicia la sesión con session_start() y verifica si existe un carrito en la sesión, creando uno vacío si no existe.
  3. Lógica de carrito:
  • Agregar producto: Incrementa la cantidad del producto si ya está en el carrito; si no, lo agrega con cantidad 1.
  • Eliminar producto: Elimina un producto específico del carrito y reindexa el array.
  1. HTML y Bootstrap:
  • Muestra la interfaz del carrito de compras con una tabla que detalla los productos, sus cantidades, precios unitarios, subtotales y opciones de acción (eliminar).
  • Calcula y muestra el total del carrito.
  1. Enlaces y navegación:
  • Un botón para proceder al pago (pago.php).
  1. Scripts y estilos:
  • Incluye estilos CSS y enlaces a las bibliotecas de Bootstrap y jQuery para un diseño y funcionalidad responsivos.

El archivo combina lógica de servidor (PHP) y estructura de presentación (HTML/CSS) para gestionar y mostrar un carrito de compras interactivo en una página web.

<?php
// Incluir la conexión a la base de datos
include 'incluir/conexion.php';

// Lógica para agregar, actualizar y eliminar productos del carrito
session_start();
if (!isset($_SESSION['carrito'])) {
    $_SESSION['carrito'] = [];
}

// Procesar acciones del carrito
if (isset($_GET['accion']) && isset($_GET['id'])) {
    $id_producto = (int)$_GET['id'];

    if ($_GET['accion'] == 'agregar') {
        // Agregar producto al carrito
        $encontrado = false;
        foreach ($_SESSION['carrito'] as &$item) {
            if ($item['id_producto'] == $id_producto) {
                $item['cantidad']++;
                $encontrado = true;
                break;
            }
        }
        if (!$encontrado) {
            $_SESSION['carrito'][] = ['id_producto' => $id_producto, 'cantidad' => 1];
        }
    } elseif ($_GET['accion'] == 'eliminar') {
        // Eliminar producto del carrito
        foreach ($_SESSION['carrito'] as $indice => $item) {
            if ($item['id_producto'] == $id_producto) {
                unset($_SESSION['carrito'][$indice]);
                break;
            }
        }
        $_SESSION['carrito'] = array_values($_SESSION['carrito']);
    }
}
?>

<!DOCTYPE html>
<html lang="es">
<head>
    <meta charset="UTF-8">
    <meta name="viewport" content="width=device-width, initial-scale=1.0">
    <title>Carrito de Compras</title>
    <link rel="stylesheet" href="recursos/css/estilos.css">
    <link rel="stylesheet" href="https://stackpath.bootstrapcdn.com/bootstrap/4.5.2/css/bootstrap.min.css">
</head>
<body>
    <?php include 'incluir/encabezado.php'; ?>

    <div class="container mt-5">
        <h1 class="text-center">Carrito de Compras</h1>
        <div class="table-responsive">
            <table class="table table-bordered">
                <thead class="thead-dark">
                    <tr>
                        <th>Producto</th>
                        <th>Cantidad</th>
                        <th>Precio Unitario</th>
                        <th>Subtotal</th>
                        <th>Acciones</th>
                    </tr>
                </thead>
                <tbody>
                    <?php
                    $total = 0;
                    if (!empty($_SESSION['carrito'])) {
                        foreach ($_SESSION['carrito'] as $item) {
                            $consulta = "SELECT * FROM productos WHERE id_producto = " . $item['id_producto'];
                            $resultado = $conexion->query($consulta);
                            if ($resultado->num_rows > 0) {
                                $producto = $resultado->fetch_assoc();
                                $subtotal = $producto['precio'] * $item['cantidad'];
                                $total += $subtotal;
                                echo '
                                <tr>
                                    <td>' . $producto['nombre'] . '</td>
                                    <td>' . $item['cantidad'] . '</td>
                                    <td>$' . number_format($producto['precio'], 2) . '</td>
                                    <td>$' . number_format($subtotal, 2) . '</td>
                                    <td>
                                        <a href="carrito.php?accion=eliminar&id=' . $item['id_producto'] . '" class="btn btn-danger btn-sm">Eliminar</a>
                                    </td>
                                </tr>
                                ';
                            }
                        }
                    } else {
                        echo '<tr><td colspan="5" class="text-center">El carrito está vacío.</td></tr>';
                    }
                    ?>
                </tbody>
            </table>
        </div>
        <h3 class="text-right">Total: $<?php echo number_format($total, 2); ?></h3>
        <div class="text-right">
            <a href="pago.php" class="btn btn-success">Proceder al Pago</a>
        </div>
    </div>

    <?php include 'incluir/pie.php'; ?>

    <script src="https://code.jquery.com/jquery-3.5.1.slim.min.js"></script>
    <script src="https://cdn.jsdelivr.net/npm/@popperjs/core@2.9.2/dist/umd/popper.min.js"></script>
    <script src="https://stackpath.bootstrapcdn.com/bootstrap/4.5.2/js/bootstrap.min.js"></script>
</body>
</html>

Archivo pago.php (Proceso de pago):

Este código es un script PHP que gestiona un proceso de pago simulado de la tienda en línea, verificando que haya productos en el carrito y calculando el total.

Se incluye el archivo conexion.php para establecer la conexión con la base de datos y se inicia una sesión con session_start() para gestionar el carrito de compras. Si el carrito está vacío (empty($_SESSION['carrito'])), el script redirige al usuario a carrito.php y finaliza la ejecución (exit()), impidiendo que se acceda al proceso de pago sin productos en el carrito.

Cuando el formulario es enviado ($_SERVER['REQUEST_METHOD'] === 'POST'), se ejecuta un bucle que recorre los productos en el carrito. Se consulta cada producto en la base de datos usando su id_producto para verificar que existe y obtener su precio, y se calcula el subtotal multiplicando el precio por la cantidad de cada producto y sumándolo al total.

La página muestra un encabezado y un formulario con un botón que simula la confirmación de compra y utiliza estilos CSS propios y los de Bootstrap para un diseño responsivo y atractivo. Se incluyen scripts de Bootstrap y jQuery para proporcionar funcionalidad y estilo a la página.

Nota: Si el carrito está vacío, el script no realiza ninguna acción relacionada con el procesamiento de pago. En lugar de eso, verifica si el carrito está vacío y, de ser así, redirige al usuario a carrito.php y termina la ejecución del script con exit(). Esto evita que se procese un pago o se muestre la interfaz de pago si no hay productos en el carrito.

<?php
// Incluir la conexión a la base de datos
include 'incluir/conexion.php';

// Iniciar sesión para acceder al carrito
session_start();

// Verificar si el carrito tiene productos
if (empty($_SESSION['carrito'])) {
    header("Location: carrito.php");
    exit();
}

// Lógica para validar los productos en el carrito
if ($_SERVER['REQUEST_METHOD'] === 'POST') {
    $total = 0;
    foreach ($_SESSION['carrito'] as $item) {
        $consulta = "SELECT * FROM productos WHERE id_producto = " . $item['id_producto'];
        $resultado = $conexion->query($consulta);
        if ($resultado->num_rows > 0) {
            $producto = $resultado->fetch_assoc();
            $total += $producto['precio'] * $item['cantidad'];
        }
    }

    // Aquí solo se muestra el total calculado sin escribir en otras tablas.
    // Puedes agregar otras acciones si es necesario.

    // Redirigir a una página de confirmación o mostrar un mensaje de éxito
    header("Location: pago_exitoso.php");
    exit();
}
?>

<!DOCTYPE html>
<html lang="es">
<head>
    <meta charset="UTF-8">
    <meta name="viewport" content="width=device-width, initial-scale=1.0">
    <title>Pago</title>
    <link rel="stylesheet" href="recursos/css/estilos.css">
    <link rel="stylesheet" href="https://stackpath.bootstrapcdn.com/bootstrap/4.5.2/css/bootstrap.min.css">
</head>
<body>
    <?php include 'incluir/encabezado.php'; ?>

    <div class="container mt-5">
        <h1 class="text-center">Proceso de Pago</h1>
        <form method="POST" action="">
            <div class="alert alert-info text-center">
                <p>Este es un proceso de pago simulado. Haz clic en "Completar Compra" para finalizar tu compra.</p>
            </div>
            <div class="text-right">
                <button type="submit" class="btn btn-success">Completar Compra</button>
            </div>
        </form>
    </div>

    <?php include 'incluir/pie.php'; ?>

    <script src="https://code.jquery.com/jquery-3.5.1.slim.min.js"></script>
    <script src="https://cdn.jsdelivr.net/npm/@popperjs/core@2.9.2/dist/umd/popper.min.js"></script>
    <script src="https://stackpath.bootstrapcdn.com/bootstrap/4.5.2/js/bootstrap.min.js"></script>
</body>
</html>

Archivo pago_exitoso.php (Confirmación de compra):

Este archivo es una página HTML que muestra un mensaje de confirmación de compra exitosa al usuario. Incluye un encabezado (incluir/encabezado.php) y un pie de página (incluir/pie.php).

El cuerpo de la página contiene un contenedor con una alerta de Bootstrap que muestra un mensaje de agradecimiento por la compra y notifica que el pedido ha sido procesado con éxito. También se proporciona un enlace con un botón que redirige al usuario de vuelta a la página de inicio (index.php). La página utiliza estilos CSS personalizados y de Bootstrap para un diseño atractivo y responsivo, y se complementa con scripts de jQuery y Bootstrap para funcionalidad adicional.

<!DOCTYPE html>
<html lang="es">
<head>
    <meta charset="UTF-8">
    <meta name="viewport" content="width=device-width, initial-scale=1.0">
    <title>Compra Exitosa</title>
    <link rel="stylesheet" href="recursos/css/estilos.css">
    <link rel="stylesheet" href="https://stackpath.bootstrapcdn.com/bootstrap/4.5.2/css/bootstrap.min.css">
</head>
<body>
    <?php include 'incluir/encabezado.php'; ?>

    <div class="container mt-5">
        <div class="alert alert-success text-center">
            <h1>¡Gracias por tu compra!</h1>
            <p>Tu pedido ha sido procesado exitosamente. Pronto recibirás un correo con los detalles de tu pedido.</p>
            <a href="index.php" class="btn btn-primary mt-3">Volver al Inicio</a>
        </div>
    </div>

    <?php include 'incluir/pie.php'; ?>

    <script src="https://code.jquery.com/jquery-3.5.1.slim.min.js"></script>
    <script src="https://cdn.jsdelivr.net/npm/@popperjs/core@2.9.2/dist/umd/popper.min.js"></script>
    <script src="https://stackpath.bootstrapcdn.com/bootstrap/4.5.2/js/bootstrap.min.js"></script>
</body>
</html>

Nota para los estudiantes

Hasta este punto, ya hemos creado la parte frontend de la tienda en línea. Con los archivos desarrollados, deberían poder probar la tienda y comprobar que todo funcione sin errores. Esto incluye la visualización de productos, el carrito de compras, y el proceso de pago simulado.

Cómo probar la tienda antes de completar el backend

Para probar las funcionalidades de la tienda, deberán ingresar un registro de producto directamente en phpMyAdmin:

  1. Accede a phpMyAdmin y selecciona la base de datos comercio_electronico.
  2. Selecciona la tabla productos.
  3. Haz clic en la pestaña “Insertar” y añade un nuevo producto con la siguiente información de ejemplo:
    • nombre: Sudadera
    • descripcion: Sudadera de algodón unisex
    • precio: 250.00
    • imagen: sudadera.png (asegúrate de que la imagen esté en la carpeta recursos/imagenes/)
    • stock: 10
  4. Guarda el registro y vuelve a tu navegador para probar la tienda en línea.

Tienes que ver algo así:

Qué puedes hacer ahora:

  • Navegar por la página de inicio (index.php), verificar que los productos se muestren correctamente.
  • Agregar productos al carrito (carrito.php) y simular una compra completa (pago.php y pago_exitoso.php).

Creación del Backend para la tienda en linea

En esta sección, desarrollaremos la interfaz de administración (backend) de la tienda en línea. Esto permitirá gestionar productos de manera sencilla a través de un panel de control. La administración incluirá funcionalidades para iniciar sesión, agregar, editar y eliminar productos.

Estructura de archivos del backend

La estructura del backend estará contenida dentro de la carpeta admin/:

tienda-en-linea/
│
├── admin/ (backend)
│   ├── inicio_sesion.php
│   ├── panel_control.php
│   ├── gestion_productos.php
│   ├── agregar_producto.php
│   └── editar_producto.php
│   └── cerrar_sesion.php

Paso 1: Crear el archivo de inicio de sesión (admin/inicio_sesion.php)

Este archivo permitirá a los administradores acceder al panel de control.

Recuerda que los datos para acceder se insertaron al inicio al crear la base de datos:

Usuario: administrador

Password: 12345

Código para inicio_sesion.php:

<?php
session_start();
include '../incluir/conexion.php';

if ($_SERVER['REQUEST_METHOD'] == 'POST') {
    $usuario = $_POST['usuario'];
    $password = $_POST['password'];

    // Verificar credenciales de administrador
    $consulta = "SELECT * FROM usuarios WHERE usuario = '$usuario' AND password = '$password'";
    $resultado = $conexion->query($consulta);

    if ($resultado->num_rows == 1) {
        $_SESSION['admin'] = $usuario;
        header("Location: panel_control.php");
        exit();
    } else {
        $error = "Usuario o contraseña incorrectos.";
    }
}
?>

<!DOCTYPE html>
<html lang="es">
<head>
    <meta charset="UTF-8">
    <meta name="viewport" content="width=device-width, initial-scale=1.0">
    <title>Inicio de Sesión - Administración</title>
    <link rel="stylesheet" href="https://stackpath.bootstrapcdn.com/bootstrap/4.5.2/css/bootstrap.min.css">
</head>
<body>
    <div class="container mt-5">
        <h2 class="text-center">Inicio de Sesión - Administración</h2>
        <?php if (isset($error)) { echo '<div class="alert alert-danger">' . $error . '</div>'; } ?>
        <form method="POST" action="">
            <div class="form-group">
                <label for="usuario">Usuario:</label>
                <input type="text" class="form-control" id="usuario" name="usuario" required>
            </div>
            <div class="form-group">
                <label for="password">Contraseña:</label>
                <input type="password" class="form-control" id="password" name="password" required>
            </div>
            <button type="submit" class="btn btn-primary btn-block">Iniciar Sesión</button>
        </form>
    </div>

    <script src="https://code.jquery.com/jquery-3.5.1.slim.min.js"></script>
    <script src="https://cdn.jsdelivr.net/npm/@popperjs/core@2.9.2/dist/umd/popper.min.js"></script>
    <script src="https://stackpath.bootstrapcdn.com/bootstrap/4.5.2/js/bootstrap.min.js"></script>
</body>
</html>

Paso 2: Crear el archivo del panel de control (admin/panel_control.php)

Este archivo será el punto de acceso principal después de iniciar sesión. Es como un menú principal, donde se pueden agregar funciones adicionales, por ahora tendrá acceso a la función “Gestionar productos”.

Código para panel_control.php:

<?php
session_start();

// Verificar si el administrador ha iniciado sesión
if (!isset($_SESSION['admin'])) {
    header("Location: inicio_sesion.php");
    exit();
}

// Incluir la conexión a la base de datos
include '../incluir/conexion.php';
?>

<!DOCTYPE html>
<html lang="es">
<head>
    <meta charset="UTF-8">
    <meta name="viewport" content="width=device-width, initial-scale=1.0">
    <title>Panel de Control - Administración</title>
    <link rel="stylesheet" href="https://stackpath.bootstrapcdn.com/bootstrap/4.5.2/css/bootstrap.min.css">
</head>
<body>
    <div class="container mt-5">
        <h2 class="text-center">Panel de Control - Administración</h2>
        <div class="text-right mb-3">
            <a href="cerrar_sesion.php" class="btn btn-danger">Cerrar Sesión</a>
        </div>
        <div class="row">
            <div class="col-md-4 mb-4">
                <div class="card">
                    <div class="card-body text-center">
                        <h5 class="card-title">Gestionar Productos</h5>
                        <p class="card-text">Agregar, editar y eliminar productos de la tienda.</p>
                        <a href="gestion_productos.php" class="btn btn-primary">Ir a Gestión de Productos</a>
                    </div>
                </div>
            </div>
            <!-- Puedes agregar más secciones aquí -->
        </div>
    </div>

    <script src="https://code.jquery.com/jquery-3.5.1.slim.min.js"></script>
    <script src="https://cdn.jsdelivr.net/npm/@popperjs/core@2.9.2/dist/umd/popper.min.js"></script>
    <script src="https://stackpath.bootstrapcdn.com/bootstrap/4.5.2/js/bootstrap.min.js"></script>
</body>
</html>

Paso 3: Crear el archivo para gestionar productos (admin/gestion_productos.php)

Este archivo mostrará una lista de productos y permitirá editarlos o eliminarlos, al mismo tiempo que mostrará una función, mediante un botón, para agregar un nuevo producto.

Código para gestion_productos.php:

<?php
session_start();
if (!isset($_SESSION['admin'])) {
    header("Location: inicio_sesion.php");
    exit();
}
include '../incluir/conexion.php';

if (isset($_GET['accion']) && $_GET['accion'] == 'eliminar' && isset($_GET['id'])) {
    $id_producto = (int)$_GET['id'];
    $conexion->query("DELETE FROM productos WHERE id_producto = $id_producto");
    header("Location: gestion_productos.php");
    exit();
}
?>

<!DOCTYPE html>
<html lang="es">
<head>
    <meta charset="UTF-8">
    <meta name="viewport" content="width=device-width, initial-scale=1.0">
    <title>Gestión de Productos</title>
    <link rel="stylesheet" href="https://stackpath.bootstrapcdn.com/bootstrap/4.5.2/css/bootstrap.min.css">
</head>
<body>
    <div class="container mt-5">
        <h2 class="text-center">Gestión de Productos</h2>
        <div class="text-right mb-3">
            <a href="agregar_producto.php" class="btn btn-success">Agregar Producto</a>
            <a href="cerrar_sesion.php" class="btn btn-danger">Cerrar Sesión</a>
        </div>
        <table class="table table-bordered">
            <thead class="thead-dark">
                <tr>
                    <th>ID</th>
                    <th>Nombre</th>
                    <th>Descripción</th>
                    <th>Precio</th>
                    <th>Stock</th>
                    <th>Acciones</th>
                </tr>
            </thead>
            <tbody>
                <?php
                $consulta = "SELECT * FROM productos";
                $resultado = $conexion->query($consulta);
                if ($resultado->num_rows > 0) {
                    while ($producto = $resultado->fetch_assoc()) {
                        echo '
                        <tr>
                            <td>' . $producto['id_producto'] . '</td>
                            <td>' . $producto['nombre'] . '</td>
                            <td>' . $producto['descripcion'] . '</td>
                            <td>$' . number_format($producto['precio'], 2) . '</td>
                            <td>' . $producto['stock'] . '</td>
                            <td>
                                <a href="editar_producto.php?id=' . $producto['id_producto'] . '" class="btn btn-warning btn-sm">Editar</a>
                                <a href="gestion_productos.php?accion=eliminar&id=' . $producto['id_producto'] . '" class="btn btn-danger btn-sm" onclick="return confirm(\'¿Estás seguro de que quieres eliminar este producto?\')">Eliminar</a>
                            </td>
                        </tr>
                        ';
                    }
                } else {
                    echo '<tr><td colspan="6" class="text-center">No hay productos disponibles.</td></tr>';
                }
                ?>
            </tbody>
        </table>
    </div>

    <script src="https://code.jquery.com/jquery-3.5.1.slim.min.js"></script>
    <script src="https://cdn.jsdelivr.net/npm/@popperjs/core@2.9.2/dist/umd/popper.min.js"></script>
    <script src="https://stackpath.bootstrapcdn.com/bootstrap/4.5.2/js/bootstrap.min.js"></script>
</body>
</html>

Paso 4: Crear el archivo para agregar productos (admin/agregar_producto.php)

Este archivo permitirá al administrador agregar nuevos productos, escribiendo los detalles de cada uno y adjuntar la imagen correspondiente, la cual se copiará a la carpeta recursos/imagenes.

Código para agregar_producto.php

<?php
session_start();

// Verificar si el administrador ha iniciado sesión
if (!isset($_SESSION['admin'])) {
    header("Location: inicio_sesion.php");
    exit();
}

// Incluir la conexión a la base de datos
include '../incluir/conexion.php';

// Manejar el envío del formulario
if ($_SERVER['REQUEST_METHOD'] == 'POST') {
    $nombre = $_POST['nombre'];
    $descripcion = $_POST['descripcion'];
    $precio = $_POST['precio'];
    $stock = $_POST['stock'];

    // Manejo de la imagen
    if (isset($_FILES['imagen']) && $_FILES['imagen']['error'] == 0) {
        $nombre_imagen = basename($_FILES['imagen']['name']);
        $ruta_destino = '../recursos/imagenes/' . $nombre_imagen;

        // Mover la imagen al directorio de destino
        if (move_uploaded_file($_FILES['imagen']['tmp_name'], $ruta_destino)) {
            // Guardar la información en la base de datos
            $consulta = "INSERT INTO productos (nombre, descripcion, precio, imagen, stock) VALUES ('$nombre', '$descripcion', $precio, '$nombre_imagen', $stock)";
            if ($conexion->query($consulta)) {
                $mensaje = "Producto agregado con éxito.";
                header("Location: gestion_productos.php?mensaje=" . urlencode($mensaje));
                exit();
            } else {
                $error = "Error al guardar el producto: " . $conexion->error;
            }
        } else {
            $error = "Error al subir la imagen.";
        }
    } else {
        $error = "No se ha seleccionado una imagen o hubo un error al subirla.";
    }
}
?>

<!DOCTYPE html>
<html lang="es">
<head>
    <meta charset="UTF-8">
    <meta name="viewport" content="width=device-width, initial-scale=1.0">
    <title>Agregar Producto</title>
    <link rel="stylesheet" href="https://stackpath.bootstrapcdn.com/bootstrap/4.5.2/css/bootstrap.min.css">
</head>
<body>
    <div class="container mt-5">
        <h2 class="text-center">Agregar Nuevo Producto</h2>
        <?php if (isset($error)) { echo '<div class="alert alert-danger">' . $error . '</div>'; } ?>
        <form action="" method="POST" enctype="multipart/form-data">
            <div class="form-group">
                <label for="nombre">Nombre del producto:</label>
                <input type="text" class="form-control" id="nombre" name="nombre" required>
            </div>
            <div class="form-group">
                <label for="descripcion">Descripción:</label>
                <textarea class="form-control" id="descripcion" name="descripcion" required></textarea>
            </div>
            <div class="form-group">
                <label for="precio">Precio:</label>
                <input type="number" step="0.01" class="form-control" id="precio" name="precio" required>
            </div>
            <div class="form-group">
                <label for="stock">Stock:</label>
                <input type="number" class="form-control" id="stock" name="stock" required>
            </div>
            <div class="form-group">
                <label for="imagen">Imagen:</label>
                <input type="file" class="form-control-file" id="imagen" name="imagen" accept="image/*" required>
            </div>
            <button type="submit" class="btn btn-success">Agregar Producto</button>
            <a href="gestion_productos.php" class="btn btn-secondary">Volver</a>
        </form>
    </div>

    <script src="https://code.jquery.com/jquery-3.5.1.slim.min.js"></script>
    <script src="https://cdn.jsdelivr.net/npm/@popperjs/core@2.9.2/dist/umd/popper.min.js"></script>
    <script src="https://stackpath.bootstrapcdn.com/bootstrap/4.5.2/js/bootstrap.min.js"></script>
</body>
</html>

Paso 5: Crear el archivo para editar productos (admin/editar_producto.php)

Este archivo permitirá al administrador editar los detalles de un producto existente, con una interfaz similar a la de agregar producto.

<?php
session_start();

// Verificar si el administrador ha iniciado sesión
if (!isset($_SESSION['admin'])) {
    header("Location: inicio_sesion.php");
    exit();
}

// Incluir la conexión a la base de datos
include '../incluir/conexion.php';

// Obtener el producto a editar
if (isset($_GET['id'])) {
    $id_producto = (int)$_GET['id'];
    $consulta = "SELECT * FROM productos WHERE id_producto = $id_producto";
    $resultado = $conexion->query($consulta);
    if ($resultado->num_rows == 1) {
        $producto = $resultado->fetch_assoc();
    } else {
        header("Location: gestion_productos.php");
        exit();
    }
} else {
    header("Location: gestion_productos.php");
    exit();
}

// Manejar el envío del formulario para actualizar el producto
if ($_SERVER['REQUEST_METHOD'] == 'POST') {
    $nombre = $_POST['nombre'];
    $descripcion = $_POST['descripcion'];
    $precio = $_POST['precio'];
    $stock = $_POST['stock'];
    $nombre_imagen = $producto['imagen']; // Imagen actual por defecto

    // Verificar si se ha subido una nueva imagen
    if (isset($_FILES['imagen']) && $_FILES['imagen']['error'] == 0) {
        $nombre_imagen = basename($_FILES['imagen']['name']);
        $ruta_destino = '../recursos/imagenes/' . $nombre_imagen;

        // Mover la nueva imagen al directorio de destino
        if (move_uploaded_file($_FILES['imagen']['tmp_name'], $ruta_destino)) {
            // Actualizar el campo de imagen en la base de datos
        } else {
            $error = "Error al subir la nueva imagen.";
        }
    }

    // Actualizar los datos en la base de datos
    $consulta = "UPDATE productos SET nombre='$nombre', descripcion='$descripcion', precio=$precio, imagen='$nombre_imagen', stock=$stock WHERE id_producto=$id_producto";
    if ($conexion->query($consulta)) {
        $mensaje = "Producto actualizado con éxito.";
        header("Location: gestion_productos.php?mensaje=" . urlencode($mensaje));
        exit();
    } else {
        $error = "Error al actualizar el producto: " . $conexion->error;
    }
}
?>

<!DOCTYPE html>
<html lang="es">
<head>
    <meta charset="UTF-8">
    <meta name="viewport" content="width=device-width, initial-scale=1.0">
    <title>Editar Producto</title>
    <link rel="stylesheet" href="https://stackpath.bootstrapcdn.com/bootstrap/4.5.2/css/bootstrap.min.css">
</head>
<body>
    <div class="container mt-5">
        <h2 class="text-center">Editar Producto</h2>
        <?php if (isset($error)) { echo '<div class="alert alert-danger">' . $error . '</div>'; } ?>
        <form action="" method="POST" enctype="multipart/form-data">
            <div class="form-group">
                <label for="nombre">Nombre del producto:</label>
                <input type="text" class="form-control" id="nombre" name="nombre" value="<?php echo $producto['nombre']; ?>" required>
            </div>
            <div class="form-group">
                <label for="descripcion">Descripción:</label>
                <textarea class="form-control" id="descripcion" name="descripcion" required><?php echo $producto['descripcion']; ?></textarea>
            </div>
            <div class="form-group">
                <label for="precio">Precio:</label>
                <input type="number" step="0.01" class="form-control" id="precio" name="precio" value="<?php echo $producto['precio']; ?>" required>
            </div>
            <div class="form-group">
                <label for="stock">Stock:</label>
                <input type="number" class="form-control" id="stock" name="stock" value="<?php echo $producto['stock']; ?>" required>
            </div>
            <div class="form-group">
                <label for="imagen">Imagen (deja en blanco si no deseas cambiarla):</label>
                <input type="file" class="form-control-file" id="imagen" name="imagen" accept="image/*">
                <small class="form-text text-muted">Imagen actual: <?php echo $producto['imagen']; ?></small>
            </div>
            <button type="submit" class="btn btn-primary">Actualizar Producto</button>
            <a href="gestion_productos.php" class="btn btn-secondary">Volver</a>
        </form>
    </div>

    <script src="https://code.jquery.com/jquery-3.5.1.slim.min.js"></script>
    <script src="https://cdn.jsdelivr.net/npm/@popperjs/core@2.9.2/dist/umd/popper.min.js"></script>
    <script src="https://stackpath.bootstrapcdn.com/bootstrap/4.5.2/js/bootstrap.min.js"></script>
</body>
</html>

Paso 6: Código para Cerrar Sesión (admin/cerrar_sesion.php)

Este archivo contiene el código para verificar la sesión abierta y destruirla, posteriormente redirige a la página inicio_sesion.php que contiene el formulario de logueo.

<?php
session_start();
session_destroy();
header("Location: inicio_sesion.php");
exit();

Explicación:

  • session_start(): Inicia la sesión para poder destruirla.
  • session_destroy(): Elimina todas las variables de la sesión, cerrando la sesión actual.
  • header("Location: inicio_sesion.php"): Redirige al administrador a la página de inicio de sesión tras cerrar la sesión.

Resumen del backend:

  • inicio_sesion.php: Permite a los administradores iniciar sesión.
  • panel_control.php: Panel de control que redirige a la gestión de productos.
  • gestion_productos.php: Permite visualizar, editar y eliminar productos.
  • agregar_producto.php: Formulario para agregar nuevos productos.
  • editar_producto.php: Formulario para editar productos existentes.
  • cerrar_sesion.php: Elimina todas las variables de sesion activa del usuario adminnistrador

2 respuestas

Responder a Hector David Montoya Midence Cancelar respuesta

Tu dirección de correo electrónico no será publicada. Los campos obligatorios están marcados con *