Carro de Compras Simple con PHP y MySQL

simple-shopping-cart

Anteriormente, hemos aprendido cómo crear un Sistema de Pedidos de Pizza con Paypal usando PHP .Hoy vamos a aprender como crear un carro de compras simple usando PHP y MySQL. 

Antes de empezar a leer este tutorial  considera los 2 ítem siguientes:

1-) Los códigos fuente de esta página NO son para usted si:

  • Ya eres un experto en programación PHP y MySQL.
  • Tienes mucho tiempo para codificar un sistema de carrito de la compra a partir de cero.
  • Usted no está tan interesado en el aprendizaje de PHP y MySQL de programación.

2-)  Los códigos fuente de esta página SI son para usted si:

  • ¿Quieres ahorrar gran cantidad de tiempo de desarrollo.
  • Se quiere desarrollar su propio sistema de carrito de la compra a partir de cero.
  • Usted decidido a aprender cómo hacer una aplicación web en PHP y MySQL.

Pero si usted es un experto en programación PHP y MySQL y quieres echar un vistazo a nuestro código, por favor hágalo! Nos gustaría escuchar su respuesta y grandes ideas! La sección de comentarios está siempre abierta para cualquier persona con preguntas y sugerencias.

Lo que haremos:

Vamos a empezar con el código fuente. Nuestro sistema simple tendrá dos páginas.

1. La página de productos (productos.php) muestra la lista de los productos recuperados de la base de datos. Para cada producto, que tiene un botón azul que dice “Añadir a la cesta”, sino que también tiene un icono de la compra.

2. La página de carro (carro.php) muestra la lista de productos que el usuario ha añadido a su cesta. Para cada elemento de la compra, que tiene un botón rojo que dice “Quitar del carrito” con un icono “x”.

productos

PROGRAMACIÓN PASO A PASO:.

Ahora bien la parte más interesante de todo esto; la programación.

Paso 1 : En su PhpMyAdmin, crear una base de datos. A continuación, ejecute las siguientes consultas SQL para crear las tablas de ejemplo.

-- phpMyAdmin SQL Dump
-- version 4.4.14
-- http://www.phpmyadmin.net
--
-- Servidor: 127.0.0.1
-- Tiempo de generación: 03-09-2016 a las 12:30:11
-- Versión del servidor: 5.6.26
-- Versión de PHP: 5.6.12
 
SET SQL_MODE = "NO_AUTO_VALUE_ON_ZERO";
SET time_zone = "+00:00";
 
 
/*!40101 SET @OLD_CHARACTER_SET_CLIENT=@@CHARACTER_SET_CLIENT */;
/*!40101 SET @OLD_CHARACTER_SET_RESULTS=@@CHARACTER_SET_RESULTS */;
/*!40101 SET @OLD_COLLATION_CONNECTION=@@COLLATION_CONNECTION */;
/*!40101 SET NAMES utf8mb4 */;
 
--
-- Base de datos: `test_shop`
--
 
-- --------------------------------------------------------
 
--
-- Estructura de tabla para la tabla `cart_items`
--
 
CREATE TABLE IF NOT EXISTS `cart_items` (
  `id` int(11) NOT NULL,
  `product_id` int(11) NOT NULL,
  `quantity` double NOT NULL,
  `user_id` int(11) NOT NULL,
  `created` datetime NOT NULL,
  `modified` timestamp NOT NULL DEFAULT CURRENT_TIMESTAMP ON UPDATE CURRENT_TIMESTAMP
) ENGINE=MyISAM DEFAULT CHARSET=utf8;
 
-- --------------------------------------------------------
 
--
-- Estructura de tabla para la tabla `products`
--
 
CREATE TABLE IF NOT EXISTS `products` (
  `id` int(11) NOT NULL,
  `name` varchar(512) NOT NULL,
  `description` text NOT NULL,
  `price` int(11) NOT NULL,
  `created` datetime NOT NULL,
  `modified` timestamp NOT NULL DEFAULT CURRENT_TIMESTAMP
) ENGINE=InnoDB AUTO_INCREMENT=11 DEFAULT CHARSET=latin1 COMMENT='productos';
 
--
-- Volcado de datos para la tabla `products`
--
 
INSERT INTO `products` (`id`, `name`, `description`, `price`, `created`, `modified`) VALUES
(1, 'Monitor LED 22 PLG S22F350FHU', 'Prueba de descripcion', 199, '2015-03-18 18:05:15', '2016-09-03 16:05:15'),
(2, 'Monitor LED Curvo 24 PLG C24F390FHU', '<ul><li><span style="font-size: 1em;">Printed</span></li><li><span style="font-size: 1em;">100% Silk</span></li><li><span style="font-size: 1em;">Dry Clean Only</span></li><li><span style="font-size: 1em;">Unlined</span></li><li><span style="font-size: 1em;">3.5" inseam</span></li><li><span style="font-size: 1em;">Model is 5''10"&nbsp;</span></li><li><span style="font-size: 1em;">Wearing a size Small</span></li></ul>', 229, '2016-03-18 23:42:04', '2016-03-18 21:42:04'),
(3, 'Monitor LED Curvo 32PLG C32F391FWU', '<ol><li><span style="font-size: 1em;">Brand: Abercrombie &amp; Fitch</span></li><li><span style="font-size: 1em;">Muscle fit</span></li><li><span style="font-size: 1em;">Composition:100% cotton,exclusive of decoration</span></li><li><span style="font-size: 1em;">Made in Vietnam.</span></li></ol>', 100, '2016-03-18 23:59:07', '2016-03-18 21:59:07'),
(4, 'Galaxy S7', 'Hemos realizado progresos importantes, superando barreras y avanzando en todo momento, escuchando los que nos tienes que decir y combinando función y forma. Hemos introducido funciones nunca vistas hasta ahora en los smartphones. ', 599, '2016-03-19 00:04:03', '2016-03-18 22:04:03'),
(5, 'Rat&oacute;n inal&aacute;mbrico l&aacute;ser Lenovo', '', 30, '2016-03-19 00:08:03', '2016-03-18 22:08:03'),
(6, 'Auriculares para juegos Lenovo Y: ROW', '', 45, '2016-03-19 09:02:16', '2016-03-19 07:02:16'),
(7, 'Altavoz Bluetooth ThinkPad Stack\r\nModelo:  4XD0H34183', '', 102, '2016-03-04 09:06:53', '2016-03-19 07:06:53'),
(8, 'ThinkStation NVIDIA Quadro K1200 (LP)', '', 399, '2016-03-19 09:18:06', '2016-03-19 07:18:06'),
(9, 'Teclado USB Lenovo ', '', 37, '2016-03-19 15:38:09', '2016-03-19 13:38:09'),
(10, 'Mouse inal&aacute;mbrico ThinkPad Precision - rojo onda de calor', '', 50, '2016-03-19 15:44:02', '2016-03-19 13:44:02');
 
--
-- Índices para tablas volcadas
--
 
--
-- Indices de la tabla `cart_items`
--
ALTER TABLE `cart_items`
  ADD PRIMARY KEY (`id`);
 
--
-- Indices de la tabla `products`
--
ALTER TABLE `products`
  ADD PRIMARY KEY (`id`);
 
--
-- AUTO_INCREMENT de las tablas volcadas
--
 
--
-- AUTO_INCREMENT de la tabla `cart_items`
--
ALTER TABLE `cart_items`
  MODIFY `id` int(11) NOT NULL AUTO_INCREMENT;
--
-- AUTO_INCREMENT de la tabla `products`
--
ALTER TABLE `products`
  MODIFY `id` int(11) NOT NULL AUTO_INCREMENT,AUTO_INCREMENT=11;
/*!40101 SET CHARACTER_SET_CLIENT=@OLD_CHARACTER_SET_CLIENT */;
/*!40101 SET CHARACTER_SET_RESULTS=@OLD_CHARACTER_SET_RESULTS */;
/*!40101 SET COLLATION_CONNECTION=@OLD_COLLATION_CONNECTION */;

Paso 2 : En el directorio raíz que haz elegido, crea una carpeta con el nombre de config.

Paso 3: Dentro de esa carpeta de configuración, crear un archivo llamado database.php .Coloca el código siguiente en su interior, basta con cambiar las credenciales de la base de datos a la que corresponda para que el código funcione.

<?php
$host = "localhost";
$db_name = "test_shop";
$username = "root";
$password = "";
 
try {
    $con = new PDO("mysql:host={$host};dbname={$db_name}", $username, $password);
}
 
//to handle connection error
catch(PDOException $exception){
    echo "Connection error: " . $exception->getMessage();
}
 
?>

 

Paso 4 : Crear un archivo llamado productos.php , vamos a recuperar los productos utilizando el código de abajo.

<?php
// connect to database
include 'config/database.php';
 
// page headers
$page_title="Lista de productos";
include 'head.php';
 
// to prevent undefined index notice
$action = isset($_GET['action']) ? $_GET['action'] : "";
$product_id = isset($_GET['product_id']) ? $_GET['product_id'] : "1";
$name = isset($_GET['name']) ? $_GET['name'] : "";
$quantity = isset($_GET['quantity']) ? $_GET['quantity'] : "1";
 
// show message
if($action=='added'){
    echo "<div class='alert alert-info'>";
        echo "<strong>{$name}</strong> ¡agregado a tu carrito!";
    echo "</div>";
}
 
else if($action=='failed'){
    echo "<div class='alert alert-info'>";
        echo "<strong>{$name}</strong> No se pudo agregar a su carrito!";
    echo "</div>";
}
 
// select products from database
$query = "SELECT p.id, p.name, p.price, ci.quantity 
        FROM products p 
            LEFT JOIN cart_items ci
                ON p.id = ci.product_id 
        ORDER BY p.name";
 
$stmt = $con->prepare( $query );
$stmt->execute();
 
// count number of products returned
$num = $stmt->rowCount();
 
if($num>0){
 
    //start table
    echo "<table class='table table-hover table-responsive table-bordered'>";
 
        // our table heading
        echo "<tr>";
            echo "<th class='textAlignLeft'>Nombre del producto</th>";
            echo "<th>Precio (USD)</th>";
            echo "<th style='width:5em;'>Cantidad</th>";
            echo "<th>Acciones</th>";
        echo "</tr>";
 
        while ($row = $stmt->fetch(PDO::FETCH_ASSOC)){
            extract($row);
 
            //creating new table row per record
            echo "<tr>";
                echo "<td>";
                    echo "<div class='product-id' style='display:none;'>{$id}</div>";
                    echo "<div class='product-name'>{$name}</div>";
                echo "</td>";
                echo "<td>&#36;" . number_format($price, 2, '.' , ',') . "</td>";
                if(isset($quantity)){
                    echo "<td>";
                             echo "<input type='text' name='quantity' value='{$quantity}' disabled class='form-control' />";
                    echo "</td>";
                    echo "<td>";
                        echo "<button class='btn btn-success' disabled>";
                            echo "<span class='glyphicon glyphicon-shopping-cart'></span> Agregado!";
                        echo "</button>";
                    echo "</td>";             
                }else{
                    echo "<td>";
                             echo "<input type='number' name='quantity' value='1' class='form-control' />";
                    echo "</td>";
                    echo "<td>";
                        echo "<button class='btn btn-primary add-to-cart'>";
                            echo "<span class='glyphicon glyphicon-shopping-cart'></span> Añadir a la cesta";
                        echo "</button>";
                    echo "</td>";
                }
            echo "</tr>";
        }
 
    echo "</table>";
}
 
// tell the user if there's no products in the database
else{
    echo "No hay productos encontrados.";
}
 
include 'footer.php';
?>

 

Paso 5 : Crear el archivo head.php , al cual hace referencia la pagina creada en el paso 4. En primer lugar, vamos a tener que crear el archivo  head.php con el siguiente código:

<!DOCTYPE html>
<html lang="es">
<head>
    <meta charset="utf-8">
    <meta http-equiv="X-UA-Compatible" content="IE=edge">
    <meta name="viewport" content="width=device-width, initial-scale=1">
    <title><?php echo isset($page_title) ? $page_title : "Sistemas Web "; ?> - DEMO</title>
     <!-- Bootstrap CSS -->
    <link href="libs/css/bootstrap.css" rel="stylesheet" media="screen">
</head>
<body>
 
    <?php include 'nav.php'; ?>
 
    <!-- container -->
    <div class="container">
 
        <div class="page-header">
            <h1><?php echo $page_title; ?></h1>
        </div>

 

Paso 6 : El archivo head.php incluye otro archivo PHP llamado nav.php.  Vamos a crear el archivo nav.php y ponemos el siguiente código.

<!-- navbar -->
<div class="navbar navbar-default navbar-static-top" role="navigation">
    <div class="container">
 
        <div class="navbar-header">
            <button type="button" class="navbar-toggle" data-toggle="collapse" data-target=".navbar-collapse">
            <span class="sr-only">Toggle navigation</span>
            <span class="icon-bar"></span>
            <span class="icon-bar"></span>
            <span class="icon-bar"></span>
            </button>
            <a class="navbar-brand" href="productos.php">Sistemas Web</a>
        </div>
 
        <div class="navbar-collapse collapse">
            <ul class="nav navbar-nav">
                <li <?php echo $page_title=="Products" ? "class='active'" : ""; ?> >
                    <a href="productos.php">Productos</a>
                </li>
                <li <?php echo $page_title=="Cart" ? "class='active'" : ""; ?> >
                    <a href="carro.php">
                        <?php
                        // query to count all product in cart
                        $query = "SELECT count(*) FROM cart_items WHERE user=1";
 
                        // prepare query statement
                        $stmt = $con->prepare( $query );
 
                        // execute query
                        $stmt->execute();
 
                        // get row value
                        $rows = $stmt->fetch(PDO::FETCH_NUM);
 
                        // return count
                        $cart_count=$rows[0];
                        ?>
                        Carrito <span class="badge" id="comparison-count"><?php echo $cart_count; ?></span>
                    </a>
                </li>
            </ul>
        </div><!--/.nav-collapse -->
 
    </div>
</div>
<!-- /navbar -->

 

Paso 7 : Ahora vamos a crear el archivo  footer.php  con el código de abajo.

</div>
    <!-- /container -->
 
<!-- jQuery library -->
 <script src="https://ajax.googleapis.com/ajax/libs/jquery/1.12.4/jquery.min.js"></script>
 
<!-- bootstrap JavaScript -->
<script src="libs/js/bootstrap.min.js"></script>
<script src="libs/js/holder.js"></script>
 
<script>
$(document).ready(function(){
    $('.add-to-cart').click(function(){
        var id = $(this).closest('tr').find('.product-id').text();
        var name = $(this).closest('tr').find('.product-name').text();
        var quantity = $(this).closest('tr').find('input').val();
        window.location.href = "agregar.php?id=" + id + "&name=" + name + "&quantity=" + quantity;
    });
 
    $('.update-quantity').click(function(){
        var id = $(this).closest('tr').find('.product-id').text();
        var name = $(this).closest('tr').find('.product-name').text();
        var quantity = $(this).closest('tr').find('input').val();
        window.location.href = "actualizar.php?id=" + id + "&name=" + name + "&quantity=" + quantity;
    });
});
</script>
 
</body>
</html>

 

Paso 8 : El archivo productos.php tiene enlaces al archivo agregar.php. Vamos a crear ese archivo agregar.php agregando el código de abajo.

<?php
// connect to database
include 'config/database.php';
 
// product details
$id = isset($_GET['id']) ?  $_GET['id'] : die;
$name = isset($_GET['name']) ?  $_GET['name'] : die;
$quantity  = isset($_GET['quantity']) ?  $_GET['quantity'] : die;
$user_id=1;
$created=date('Y-m-d H:i:s');
 
// insert query
$query = "INSERT INTO cart_items SET product_id=?, quantity=?, user_id=?, created=?";
 
// prepare query
$stmt = $con->prepare($query);
 
// bind values
$stmt->bindParam(1, $id);
$stmt->bindParam(2, $quantity);
$stmt->bindParam(3, $user_id);
$stmt->bindParam(4, $created);
 
// if database insert succeeded
if($stmt->execute()){
    header('Location: productos.php?action=added&id=' . $id . '&name=' . $name);
}
 
// if database insert failed
else{
     header('Location: productos.php?action=failed&id=' . $id . '&name=' . $name);
}

 

Paso 9 : Ahora bien, si los productos que estaban en el carro, tendremos que verlo usando carro.php. Crearemos que carro.php archivo con los siguientes códigos.

<?php
// connect to database
include 'config/database.php';
 
// page headers
$page_title="Carrito";
include 'head.php';
 
// parameters
$action = isset($_GET['action']) ? $_GET['action'] : "";
$name = isset($_GET['name']) ? $_GET['name'] : "";
 
// display a message
if($action=='removed'){
    echo "<div class='alert alert-info'>";
        echo "<strong>{$name}</strong> fue eliminado del carrito!";
    echo "</div>";
}
 
else if($action=='quantity_updated'){
    echo "<div class='alert alert-info'>";
        echo "<strong>{$name}</strong> la cantidad ha sido actualizada!";
    echo "</div>";
}
 
else if($action=='failed'){
        echo "<div class='alert alert-info'>";
        echo "<strong>{$name}</strong> no se pudo actualizar la cantidad!";
    echo "</div>";
}
 
else if($action=='invalid_value'){
        echo "<div class='alert alert-info'>";
        echo "<strong>{$name}</strong> cantidad es inválida!";
    echo "</div>";
}
 
// select products in the cart
$query="SELECT p.id, p.name, p.price, ci.quantity, ci.quantity * p.price AS subtotal  
            FROM cart_items ci  
                LEFT JOIN products p 
                    ON ci.product_id = p.id"; 
 
$stmt=$con->prepare( $query );
$stmt->execute();
 
// count number of rows returned
$num=$stmt->rowCount();
 
if($num>0){
 
    //start table
    echo "<table class='table table-hover table-responsive table-bordered'>";
 
    // our table heading
    echo "<tr>";
        echo "<th class='textAlignLeft'>Nombre del producto</th>";
        echo "<th>Precio (USD)</th>";
            echo "<th style='width:15em;'>Cantidad</th>";
            echo "<th>Sub Total</th>";
            echo "<th>Acciones</th>";
    echo "</tr>";
 
    $total=0;
 
    while( $row = $stmt->fetch(PDO::FETCH_ASSOC)){
        extract($row);
 
        echo "<tr>";
            echo "<td>";
                        echo "<div class='product-id' style='display:none;'>{$id}</div>";
                        echo "<div class='product-name'>{$name}</div>";
            echo "</td>";
            echo "<td>&#36;" . number_format($price, 2, '.', ',') . "</td>";
            echo "<td>";
                        echo "<div class='input-group'>";
                            echo "<input type='number' name='quantity' value='{$quantity}' class='form-control'>";
 
                            echo "<span class='input-group-btn'>";
                                echo "<button class='btn btn-info update-quantity' type='button'><i class='glyphicon glyphicon-refresh'></i> Actualizar</button>";
                            echo "</span>";
 
                        echo "</div>";
                echo "</td>";
                echo "<td>&#36;" . number_format($subtotal, 2, '.', ',') . "</td>";
                echo "<td>";
            echo "<a href='eliminar.php?id={$id}&name={$name}' class='btn btn-danger'>";
                        echo "<span class='glyphicon glyphicon-remove'></span> Quitar del carrito";
            echo "</a>";
            echo "</td>";
        echo "</tr>";
 
        $total += $subtotal;
    }
 
    echo "<tr>";
    echo "<td><b>Total</b></td>";
    echo "<td></td>";
    echo "<td></td>";
    echo "<td>&#36;" . number_format($total, 2, '.', ',') . "</td>";
    echo "<td>";
            echo "<a href='#' class='btn btn-success'>";
            echo "<span class='glyphicon glyphicon-shopping-cart'></span> Pagar";
            echo "</a>";
    echo "</td>";
    echo "</tr>";
 
    echo "</table>";
}else{
    echo "<div class='alert alert-danger'>";
    echo "<strong>No se han encontrado productos</strong> en tu carrito!";
    echo "</div>";
}
 
 
include 'footer.php';
?>

Paso 10 : enlaces del archivo caro.php a un archivo llamado eliminar.php  para eliminar un elemento de la compra. Crearemos eliminar.php con los códigos a continuación.

<?php
// connect to database
include 'config/database.php';
 
// get the product id
$id = isset($_GET['id']) ? $_GET['id'] : "";
$name = isset($_GET['name']) ? $_GET['name'] : "";
$user_id=1;
 
// delete query
$query = "DELETE FROM cart_items WHERE product_id=? AND user_id=?";
 
// prepare query
$stmt = $con->prepare($query);
 
// bind values
$stmt->bindParam(1, $id);
$stmt->bindParam(2, $user_id);
 
// execute query
if($stmt->execute()){
    // redirect and tell the user product was removed
    header('Location: carro.php?action=removed&id=' . $id . '&name=' . $name);
}
 
// if remove failed
else{
    // redirect and tell the user it failed
    header('Location: carro.php?action=failed&id=' . $id . '&name=' . $name);
}
?>

Paso 11 : enlaces del archivo caro.php a un archivo llamado actualizar.php  para actualizar un elemento de la compra. Crearemos actualizar.php con los códigos a continuación.

<?php
// connect to database
include 'config/database.php';
 
// get the product id
$id = isset($_GET['id']) ? $_GET['id'] : "";
$name = isset($_GET['name']) ? $_GET['name'] : "";
$quantity = isset($_GET['quantity']) ? $_GET['quantity'] : "";
$quantity=intval($quantity);
$user_id=1;
 
// delete query
$query = "UPDATE cart_items SET quantity=? WHERE product_id=? AND user_id=?";
 
// prepare query
$stmt = $con->prepare($query);
 
// bind values
$stmt->bindParam(1, $quantity);
$stmt->bindParam(2, $id);
$stmt->bindParam(3, $user_id);
 
// execute query
if($stmt->execute()){
    // redirect and tell the user product was removed
    header('Location: carro.php?action=quantity_updated&id=' . $id . '&name=' . $name);
}
 
// if remove failed
else{
    // redirect and tell the user it failed
    header('Location: carro.php?action=failed&id=' . $id . '&name=' . $name);
}
?>

 

CÓDIGO FUENTE PARA DESCARGAR

Puedes obtener el código fuente siguiendo paso a paso la explicación en su conjunto, bien detallado en este tutorial.

Hay una pequeño costo monetario de USD 9.99  para obtener el código fuente completo

 

boton-mas-informacion