Catàleg: diferència entre les revisions

De Wiki personal d'en Guillem Serrat
Cap resum de modificació
Cap resum de modificació
Línia 14: Línia 14:
Dins de l'aplicació, hi ha un botó en forma de cistell que mostra la quantitat d'unitats de tots els productes es troba dins del cistell
Dins de l'aplicació, hi ha un botó en forma de cistell que mostra la quantitat d'unitats de tots els productes es troba dins del cistell
[[Fitxer:Cistell.png|center|miniatura|130x130px]]
[[Fitxer:Cistell.png|center|miniatura|130x130px]]
Inicialment, la quantitat de productes és 0, però en cas que, desde la sessió es comprovi que hi ha productes, per cada producte revisarà la seva quantitat (es pot consultar [[Afegir productes al cistell des del catàleg#Exemple de model de dades de l'array $SESSION[cistell] amb productes|Exemple de model de dades de l'array $SESSION[cistell] amb productes]] per entendre el model de dades del cistell).
Inicialment, la quantitat de productes és 0, però en cas que, desde la sessió es comprovi que hi ha productes, per cada producte revisarà la seva quantitat (es pot consultar l'[[Afegir productes al cistell des del catàleg#Exemple de model de dades de l'array $SESSION[cistell] amb productes|Exemple de model de dades de l'array $SESSION[cistell] amb productes]] per entendre el model de dades del cistell).


Un cop recuperi la quantitat del producte, sumarà aquesta quantitat al comptador. Això es realitzarà per cada producte, fins tenir la suma de totes les quantitats de tots els productes.<pre>
Un cop recuperi la quantitat del producte, sumarà aquesta quantitat al comptador. Això es realitzarà per cada producte, fins tenir la suma de totes les quantitats de tots els productes.<pre>

Revisió del 21:09, 30 des 2025

Inicialització de la sessió i connexió a la BD

Sempre que es treballa amb sessions, el primer que hem de fer és iniciar-la abans d'escriure el codi HTML

session_start();

A partir d'aquí, l'element principal d'aquesta aplicació és el cistell, el qual està present a la sessió i requerit per la majoria de codis. Per això, hem de comprovar que estigui creat, i en cas que no ho estigui, que es creï.

// Inicialitzar cistell if (!isset($_SESSION['cistell']) || !is_array($_SESSION['cistell'])) { // Si el cistell no està inicialitzat o no és una array

   $_SESSION['cistell'] = array();

}

A més, hem de requerir una connexió a la BD. En aquest cas, dins del catàleg únicament mostrarem els productes i no farem cap modificació a la BD, per tant farem servir la connexió de lectura.

require_once "./connexioBD/connexioR.php";

Comptador del cistell

Dins de l'aplicació, hi ha un botó en forma de cistell que mostra la quantitat d'unitats de tots els productes es troba dins del cistell

Inicialment, la quantitat de productes és 0, però en cas que, desde la sessió es comprovi que hi ha productes, per cada producte revisarà la seva quantitat (es pot consultar l'[[Afegir productes al cistell des del catàleg#Exemple de model de dades de l'array $SESSION[cistell] amb productes|Exemple de model de dades de l'array $SESSION[cistell] amb productes]] per entendre el model de dades del cistell).

Un cop recuperi la quantitat del producte, sumarà aquesta quantitat al comptador. Això es realitzarà per cada producte, fins tenir la suma de totes les quantitats de tots els productes.

// Comptador de productes al cistell
$comptador = 0; // El comptador inicial és 0
foreach ($_SESSION['cistell'] as $prod) { // Per cada producte
    if (is_array($prod) && isset($prod['quantitat'])) { // Ens assegurem que el producte és una array i que el vector "quantitat" existeix
        $comptador = $comptador + (int)$prod['quantitat']; // Asignem que comptador és igual al comptador més la quantitat (convertida a int)
    }
}

Obtenció de productes amb i sense cerca

El següent pas serà fer una consulta SQL per recuperar els productes de la BD. En cas que s’hagi realitzat una cerca, ho sabrem ja que s’ha enviat un formulari GET amb el camp “nom” o el camp “categoria”

Per tant, si es cerca per nom, ens arribarà el camp "nom" i aprovarà el següent condicional

// Filtrar per nom
    if (!empty($_GET['nom'])) { // En cas que s'hagi rebut algun valor pel camp "nom" (i per tant fer una cerca per nom)
        $cerca = "nom"; // Definim que a la consulta SQL es filtrarà per nom
        $valor = "%" . $_GET['nom'] . "%"; // Afegim els % degut a que és sintaxis de les consultes SQL
        $sql = "SELECT * FROM productes WHERE $cerca LIKE :valor"; // Exemple: SELECT * FROM productes WHERE nom LIKE %pc%
        $stmt = $pdo->prepare($sql);
        $stmt->bindParam(':valor', $valor);
        $stmt->execute();

En canvi, si ens arriba el camp "categoria", aprovarà el següent condicional

// Filtrar por categoría

   } elseif (!empty($_GET['categoria'])) { // En cas que s'hagi rebut algun valor pel camp "categoria" (i per tant fer una cerca per categoria)
       $cerca = "categoria"; // Definim que a la consulta SQL es filtrarà per categoria
       $valor = "%" . $_GET['categoria'] . "%"; // Afegim els % degut a que és sintaxis de les consultes SQL
       $sql = "SELECT * FROM productes WHERE $cerca LIKE :valor"; // Exemple: SELECT * FROM productes WHERE categoria LIKE %periferic%
       $stmt = $pdo->prepare($sql);
       $stmt->bindParam(':valor', $valor);
       $stmt->execute();

Si pel contrari no arriba cap cerca (i per tant, volem obtenir tots els productes de la BD), s'aprovarà el següent condicional

// En cas que no s'hagi enviat cap camp del formulari (no hi ha cap cerca)

   } else {
       $sql = "SELECT * FROM productes"; // Consulta per defecte, tots els productes
       $stmt = $pdo->prepare($sql);
       $stmt->execute();
   }

Per últim, sigui quina sigui la consulta realitzada, la desarem a la variable $productes preparada per ser recorreguda per un foreach

$productes = $stmt->fetchAll();

Mostra de missatges d'error o èxit

Quan s'afageix un producte al cistell, el procés el realitza el codi processa.php, que depenent del resultat de l'operació, ens pot enviar un missatge d'èxit o d'error mitjançant la sessió

// Si processa.php realitza correctament l'operació, catàleg.php veuria el següent:
$_SESSION['missatge_ok'] = "S'ha afegit $quantitat {$producte['nom']} al cistell.";

// Si processa.php no realitza correctament l'operació, catàleg.php veuria el següent:
$_SESSION['missatge_error'] = "X" // Depenent de l'error es mostrarà un missatge o un altre 

Per tant, dins del catàleg hem de comprovar si hem rebut aquest missatge (ja sigui el d'error o èxit), i en cas afirmatiu, mostrar-lo

<!-- Missatge de confirmació d'accions -->

       <center>
       <?php if (isset($_SESSION['missatge_ok'])): // Quan s'enviï un missatge de confirmació?>
           <p style="color: green; font-weight: bold;">
               <?php
                   echo htmlspecialchars($_SESSION['missatge_ok']); // Mostrem el missatge
                   unset($_SESSION['missatge_ok']); // Eliminem el missatge, així al recarregar la pàgina no tornarà a sortir, únicament mostrant-se un sol cop
               ?>
           </p>
       <?php endif; ?>
       </center>
       <!-- Missatge d'error -->
       <center>
       <?php if (isset($_SESSION['missatge_error'])): // Quan s'enviï un missatge d'error?>
           <p style="color: red; font-weight: bold;">
               <?php
                   echo htmlspecialchars($_SESSION['missatge_error']); // Mostrem el missatge
                   unset($_SESSION['missatge_error']); // Eliminem el missatge, així al recarregar la pàgina no tornarà a sortir, únicament mostrant-se un sol cop
               ?>
           </p>
       <?php endif; ?>
       </center>

Botons de navegació i formulari de cerca

A la part superior esquerra, es troba un botó que permet accedir als usuaris autoritzats a una secció de l'aplicació que permet realitzar tasques de gestió del catàleg

A la part superior dreta es troba un botó que permet accedir al cistell per comprar els productes. Aquest botó també mostra el valor de la variable $comptador, que representa

Formulari de cerca

Mostra de productes i gestió de l'stock

Gestió de l'stock segons unitats al cistell i a la BD

Abans de documentar la mostra de productes, definirem com gestionar la visualització de l’estoc.

Suposem que a la base de dades tenim 10 unitats en estoc i afegim 2 productes al cistell:

  • A la base de dades encara apareixen 10 unitats, perquè la compra no s’ha completat.
  • Tot i així, només queden 8 unitats disponibles per afegir al cistell, ja que 2 ja estan “reservades” dins del cistell.

Si només ens guiéssim per l’stock de la base de dades, podríem continuar afegint productes al cistell de manera indefinida fins a l’hora de la compra, cosa que generaria un problema si l’estoc real ja no és suficient.

És per això que hem de definir un “stock visible”, per evitar que els usuaris afegeixin mes productes dels possibles al cistell, però sense tocar la BD, en cas que es buidi el cistell.

Per això primer hem de saber si dins del cistell es troba el producte del que volem mostrar l'stock (mitjançant una cerca per ID de producte). En cas afirmatiu, desem a una variable la quantitat que hi ha dins del cistell

// Estoc reservat al cistell
                $reservat = 0; 
                if (isset($_SESSION['cistell'][$p['id']])) { // Dintre del cistell, comprova si algun dels productes té la mateixa ID que els productes retornats a la consulta SQL (comprova que el producte estigui al cistell)
                    $reservat = (int)$_SESSION['cistell'][$p['id']]['quantitat']; // El reservat és, dins del cistell, la quantitat d'aquell producte
                }

Un cop desada la quantitat d'aquell producte al cistell, restarem aquest nombre a l'stock de la BD, retornant el nombre d'unitats que podem afegir al cistell (una mena d'stock visible, per evitar haver d'anar retirant i afegint stock a la BD cada cop que es retira o s'afageix una unitat al cistell)

$estoc_visible = $p['estoc'] - $reservat; // L'estoc visible (que no real) del producte és l'stock real menys al reservat // Així, si hi ha productes al cistell, els restem de l'stock, però no a la BD, ja que es possible que es retirin productes

Uns punts clau per entedre aquesta gestió de l'stock són

  • L’stock visible és la quantitat de productes que l’usuari pot afegir al cistell.
  • L’stock de la BD es resta segons els productes del cistell. En el moment de fer la compra final, aquesta resta es fa a la BD en sí i s’actualitza l’stock
  • Exemples
    • Si hi ha 10 a la BD i 0 al cistell: Stock visible = 10
    • Si hi ha 10 a la BD i 5 al cistell: Stock visible = 5
    • Si hi ha 10 a la BD i 8 al cistell stock visible = 2

Mostra de productes

Un cop definit el procés de gestió de l'stock, podem definir com es mostren els productes.

A partir de la variables $productes, la qual incorpora el resultat de la consulta SQL segons hi hagi o no hagut una cerca prèvia, mostrarem els productes.

Mitjançant un foreach per cada producte mostrarem tots els detalls del producte

<?php foreach ($productes as $p): ?>

Primer el càlcul de l'stock visible

<?php

               // Estoc reservat al cistell
               $reservat = 0; 
               if (isset($_SESSION['cistell'][$p['id']])) { // Dintre del cistell, comprova si algun dels productes té la mateixa ID que els productes retornats a la consulta SQL (comprova que el producte estigui al cistell)
                   $reservat = (int)$_SESSION['cistell'][$p['id']]['quantitat']; // El reservat és, dins del cistell, la quantitat d'aquell producte
               }
               $estoc_visible = $p['estoc'] - $reservat; // L'estoc visible (que no real) del producte és l'stock real menys al reservat
               // Així, si hi ha productes al cistell, els restem de l'stock, però no a la BD, ja que es possible que es retirin productes

?>

Seguidament, la mostra de les característiques del producte (la imatge, el nom, la categoria, el preu, etc)

<!-- Mostrem la imatge -->

           <div class="product-image">
               <img src="imatges/<?php echo htmlspecialchars($p['imatge']); ?>"
               alt="<?php echo htmlspecialchars($p['nom']); ?>">
           </div>
           <!-- Mostrem el nom -->
           <h3><?php echo htmlspecialchars($p['nom']); ?></h3>
           <!-- Mostrem la categoria -->
           <p><strong>Categoria:</strong> <?php echo htmlspecialchars($p['categoria']); ?></p>
           <!-- Mostrem la descripció -->
           <p><?php echo htmlspecialchars($p['descripcio']); ?></p>
           <!-- Mostrem el preu -->
           <p>Preu: <?php echo number_format($p['preu'], 2); ?> €</p>

Finalment, en cas de que l'stock visible (BD - Cistell) sigui 0, mostrarem un text indicant que no hi ha stock. En cas que si que n'hi hagi, mostrarem, definirem una entrada numèrica on l'usuari podrà indicar quin nombre d'unitats d'aquell producte vol afegir al cistell.

La entrada numèrica tindrà com a màxim l'stock visible (Stock BD = 10; Cistell = 2; Stock visible = 8 i per tant únicament podrà afegir 8 unitats més al cistell)

El botó per afegir un producte al cistell crida al codi processa.php definint el valor “afegir” a la variable “acció”, a més de passar la ID del producte i la quantitat

<!-- Mostrem l'stock visible (stock de la BD menys el que hi ha el cistell) -->
            <p>Estoc disponible: <?php echo $estoc_visible; ?></p> 

            <!-- Si l'stock visible es major a 0 (és a dir, l'stock a la BD, restant el que hi ha al cistell) -->
            <?php if ($estoc_visible > 0): ?>
                <!-- Mostrem el formulari per afegir al cistell -->
                <form action="processa.php?accio=afegir" method="post"> <!-- Acció és a proccessa.php definint la variable "accio" com "afegir" -->
                    <input type="hidden" name="id" value="<?php echo (int)$p['id']; ?>"> <!-- Afegim un camp ocult el qual és per enviar la ID del producte (el client no ho ha de veure, ha de ser comunicació interna) -->

                    <label>
                        <!-- Definim la quantitat que podem afegir al cistell amb una sola operació -->
                        Quantitat:
                        <input type="number"
                            name="quantitat"
                            value="1"
                            min="1"
                            max="<?php echo $estoc_visible; ?>"> <!-- El nombre màxim d'unitats que es poden afegir al cistell és l'stock visible, per evitar afegir més productes dels possibles -->
                    </label>

                    <input type="submit" value="Afegeix al cistell">
                </form>
            <?php else: ?> <!-- En cas que l'stock visible sigui igual a zero, mostrarem producte esgotat, sense la possibilitat d'agefir al cistell -->
                <p><strong>Producte esgotat</strong></p>
            <?php endif; ?>

Tot aquest procés es realitza per cada producte

Un exemple de com es veuria un producte seria el següent

Fluxe de l'aplicació

Si és la primera vegada que s'entra a l'aplicació, el flux serà el següent:

  1. Es crea el cistell
  2. Comptador del cistell mostra 0 unitats
  3. Obtenció de productes sense cerca
  4. Mostra de productes (amb l'stock de tots els productes obtinguts de la BD)
  5. S'afageix un producte amb X unitats al cistell
  6. Es redirigeix al catàleg

Si s'entra al catàleg després d'afegir un producte al cistell, el flux serà el següent:

  1. Comptador del cistell mostra X unitats (les afegides)
  2. Obtenció de productes sense cerca
  3. Mostra del missatge d'èxit
  4. Mostra de productes (amb l'stock real calculat d'aquell producte afegit, no obtingut de la BD)

Codi sencer