Esercizio con vettore associativo multidimensionale e form di filtro in PHP

In queste pagine abbiamo introdotto il PHP e le sue peculiarità concentrando l’attenzione sulle form (ad es. qui) e gli array associativi (ad es. leggi qui). Vediamo un esercizio con vettore associativo multidimensionale e una form di filtro in modo da racchiudere molti di questi primi e fondamentali elementi del dello scripting PHP. In particolare vogliamo:

  • creiamo una paginetta php di prova
  • creare un vettore associativo multidimensionale (es. articoli di magazzino, con categoria, prezzo, nome, descrizione, iva, codice)
  • stampiamo il vettore sotto forma di tabella con una grafica il più possibile gradevole (ad es. con Bootstrap)
  • per ogni riga inseriamo un link che richiami un secondo script php che prende informazioni via URL/GET e stampa i dettagli della riga
  • (DIFFICILE) inseriamo una piccola form di filtro con una tendina ed un bottone di invio dove possiamo selezionare una categoria e filtrare/visualizzare la tabella precedente con solo gli articoli opportuni

La pagina iniziale

Procediamo per step incrementali. Tralasciamo l’ultimo punto più complesso in fondo a questo articolo dopo aver sviluppato i punti precedenti basilari.

Cominciamo dal creare la struttura delle cartelle css/img/js e i due file richiesti index.php e dettagli.php. Entrambi gli script possiamo già riempirli col template base di Bootstrap (lo trovi qui) per ottenere un risultato grafico più gradevole. Il risultato potrebbe essere quello che segue.

<!doctype html>
<html lang="en">
  <head>
    <meta charset="utf-8">
    <meta name="viewport" content="width=device-width, initial-scale=1">
    <title>Esercizio 00</title>
    <link href="https://cdn.jsdelivr.net/npm/bootstrap@5.3.2/dist/css/bootstrap.min.css" rel="stylesheet" integrity="sha384-T3c6CoIi6uLrA9TneNEoa7RxnatzjcDSCmG1MXxSR1GAsXEV/Dwwykc2MPK8M2HN" crossorigin="anonymous">
  </head>
  <body>
    <div class="container">
    <h1>La mia lista di articoli</h1>


     </div>
    <script src="https://cdn.jsdelivr.net/npm/bootstrap@5.3.2/dist/js/bootstrap.bundle.min.js" integrity="sha384-C6RzsynM9kWDrMNeT87bh95OGNyZPhcTNXj1NW7RuBCsyN/o0jlpcV8Qyq46cDfL" crossorigin="anonymous"></script>
  </body>
</html>

Il vettore associativo multidimensionale

Occupiamoci della prima richiesta del nostro esercizio php e del vettore associativo multidimensionale. Apriamo una coppia di tag <?php e scriviamo in modo il più leggibile possibile il vettore, vendo cura di inserire più righe con valori di esempio.

$magazzino = 
[
    "ID000" => ["nome"=>"Borsa in pelle", "descrizione"=>"Borsa in pelle da donna in cuoio marrone", "prezzounitario"=>200.50, "iva"=>22, "categoria"=>"abbigliamento"],
    "ID001" => ["nome"=>"Mocassino in cuoio", "descrizione"=>"Mocassino in cuoio marrone", "prezzounitario"=>60.00, "iva"=>22, "categoria"=>"abbigliamento"],
    "ID002" => ["nome"=>"Scolapasta elettrico", "descrizione"=>"Scolapasta a pile", "prezzounitario"=>15.90, "iva"=>22, "categoria"=>"casa"],
    "ID003" => ["nome"=>"Cioccolatini misti", "descrizione"=>"Scatola cioccolatini assortiti", "prezzounitario"=>10.00, "iva"=>10, "categoria"=>"alimentari"],
    "ID004" => ["nome"=>"Tazza latte", "descrizione"=>"Tazza cilindrica in ceramica con manico", "prezzounitario"=>6.00, "iva"=>22, "categoria"=>"casa"]
]

Prestiamo ben attenzione alle virgole e le voci con i relativi dati inventati. La struttura del vettore deve essere analoga in ogni parte similare, anche nell’uso delle virgolette.

Passo successivo, prepariamo la tabella. Ci sono due elementi della tabella da tenere presenti l’intestazione/piede che è statica, codice da scrivere una tantum senza doverlo replicare. Il codice lo possiamo scrivere da zero o copiare dal manuale di Bootstrap senza troppi complimenti (vedi qui). Non ci resta che inserire la parte di codice dinamica, nel listato rappresentato col ….?

<table class="table table-bordered">
<thead>
    <tr>
      <th scope="col">#</th>
      <th scope="col">Nome</th>
      <th scope="col">Descrizione</th>
      <th scope="col">Categoria</th>
      <th scope="col">Dettagli</th>
    </tr>
  </thead>
  <tbody>

.....?

</tbody>  
</table>

Apriamo nuovamente i tag <?php ?>. Come vedete possiamo piazzarli in più punti del listato html per far eseguire al server solo porzioni ridotte di codice php. Quello che segue credo di poter affermare sia un frammento di codice fondamentale da padroneggiare per un programmatore PHP. E’ vero che lo stesso risultato si possa ottenere in più modi ma il principio rimane fondamentale. Apriamo un ciclo, qui scegliamo il foreach ma poteva essere in modo analogo un while o for con qualche passaggio in più. Il foreach ci consente di creare due indici che puntano alla struttura del nostro vettore associativo, qui $codice che contiene l’indice IDXXX e $ articolo che conterrà l’intero sub-array associativo con le informazioni vere e proprie dell’articolo. Possiamo così piazzare i dati in comode variabili con nomi più semplici da scrivere, da riutilizzare ed immergere con più facilità nel codice successivo.

  foreach ($magazzino as $codice => $articolo)
  {
    $nome = $articolo["nome"];
    $descrizione = $articolo["descrizione"];
    $prezzounitario = $articolo["prezzounitario"];
    $categoria = $articolo["categoria"];

    echo "<td>$codice</td>";
    echo "<td>$nome</td>";
    echo "<td>$descrizione</td>";
    echo "<td>$categoria</td>";
    echo "<td><a href=\"dettaglio.php\">Leggi tutto=></a></td>";
    echo "</tr>";
  
  }

Possiamo salvare ed eseguirci lo script col nostro web server preferito in localhost o su un dominio di prova tipo Altervista o Host000.

La stampa con colore alternato

Complichiamoci la vita, ed aggiungiamo la zebratura alternata per le righe bianche/grige. In realtà per il programmatore in erba è un problema visto e rivisto, solo ora con una applicazione grafica di realtà. Ci occorrerà una variabile per contare le righe ed una if che ci permetta di scegliere righe dispari e pari. A quel punto le righe dispari le possiamo modificare aggiungendo una classe di Bootstrap che inserisce il colore di sfondo. L’indice va ovviamente incrementato a fine stampa/giro.

<!doctype html>
<html lang="en">
  <head>
    <meta charset="utf-8">
    <meta name="viewport" content="width=device-width, initial-scale=1">
    <title>Esercizio 00</title>
    <link href="https://cdn.jsdelivr.net/npm/bootstrap@5.3.2/dist/css/bootstrap.min.css" rel="stylesheet" integrity="sha384-T3c6CoIi6uLrA9TneNEoa7RxnatzjcDSCmG1MXxSR1GAsXEV/Dwwykc2MPK8M2HN" crossorigin="anonymous">
  </head>
  <body>
    <div class="container">
    <h1>La mia lista di articoli</h1>

<?php
//voglio creare un vettore associativo di articoli
//li stampa con una tabella graficamente gradevole a righe alternate
//per ogni riga inserisco un link che punta ad un secondo script che mostra i dettagli
//in questa stessa pagina inserisco un filtro per visualizzare in tabella solo un dettaglio come la catagoria

$magazzino = 
[
    "ID000" => ["nome"=>"Borsa in pelle", "descrizione"=>"Borsa in pelle da donna in cuoio marrone", "prezzounitario"=>200.50, "iva"=>22, "categoria"=>"abbigliamento"],
    "ID001" => ["nome"=>"Mocassino in cuoio", "descrizione"=>"Mocassino in cuoio marrone", "prezzounitario"=>60.00, "iva"=>22, "categoria"=>"abbigliamento"],
    "ID002" => ["nome"=>"Scolapasta elettrico", "descrizione"=>"Scolapasta a pile", "prezzounitario"=>15.90, "iva"=>22, "categoria"=>"casa"],
    "ID003" => ["nome"=>"Cioccolatini misti", "descrizione"=>"Scatola cioccolatini assortiti", "prezzounitario"=>10.00, "iva"=>10, "categoria"=>"alimentari"],
    "ID004" => ["nome"=>"Tazza latte", "descrizione"=>"Tazza cilindrica in ceramica con manico", "prezzounitario"=>6.00, "iva"=>22, "categoria"=>"casa"]
]

?>

<table class="table table-bordered">
<thead>
    <tr>
      <th scope="col">#</th>
      <th scope="col">Nome</th>
      <th scope="col">Descrizione</th>
      <th scope="col">Categoria</th>
      <th scope="col">Dettagli</th>
    </tr>
  </thead>
  <tbody>

<?php
  $indice = 0;

  foreach ($magazzino as $codice => $articolo)
  {
    $nome = $articolo["nome"];
    $descrizione = $articolo["descrizione"];
    $prezzounitario = $articolo["prezzounitario"];
    $categoria = $articolo["categoria"];

    if ($indice % 2 == 0)
      echo "<tr>";
    else
      echo "<tr class=\"table-secondary\">";

    echo "<td>$codice</td>";
    echo "<td>$nome</td>";
    echo "<td>$descrizione</td>";
    echo "<td>$categoria</td>";
    echo "<td><a href=\"dettaglio.php\">Leggi tutto=></a></td>";
    echo "</tr>";

    $indice += 1; 
   
  }
   
?>

</tbody>  
</table>

    <script src="https://cdn.jsdelivr.net/npm/bootstrap@5.3.2/dist/js/bootstrap.bundle.min.js" integrity="sha384-C6RzsynM9kWDrMNeT87bh95OGNyZPhcTNXj1NW7RuBCsyN/o0jlpcV8Qyq46cDfL" crossorigin="anonymous"></script>
  </body>
</html>

Lo script dettagli

Vediamo lo script che visualizza i dettagli del singolo articolo della tabella. Nelle tabelle precedenti abbiamo riportato in modo semplicistico la riga

    echo "<td><a href=\"dettaglio.php\">Leggi tutto=></a></td>";

Vogliamo passare allo script tutti valori da stampare in dettaglio. Nulla di più semplice visto che sappiamo come funziona la gestione del GET sia da parte dell’url, sia dal reperimento dei valori della variabile superglobale.

$prezzo = $articolo["prezzounitario"];
$iva = $articolo["iva"];
<a href=\"dettagli.php?codice=$codice&nome=$nome&descrizione=$descrizione&prezzo=$prezzo&categoria=$categoria&iva=$iva>Leggi tutto=></a></td>";

Non ci resta che preaparare lo script dettagli.php dove preleviamo i valori del $_GET e li stampiamo

<!doctype html>
<html lang="en">
  <head>
    <meta charset="utf-8">
    <meta name="viewport" content="width=device-width, initial-scale=1">
    <title>Dettagli Articolo</title>
    <link href="https://cdn.jsdelivr.net/npm/bootstrap@5.3.2/dist/css/bootstrap.min.css" rel="stylesheet" integrity="sha384-T3c6CoIi6uLrA9TneNEoa7RxnatzjcDSCmG1MXxSR1GAsXEV/Dwwykc2MPK8M2HN" crossorigin="anonymous">
  </head>
  <body>
    <div class="container">
    <h1>Dettagli articolo</h1>
    <?php
    
    if (isset($_GET['nome']))
    {
        $codice = $_GET['codice'];
        $nome = $_GET['nome'];
        $descrizione = $_GET['descrizione'];
        $prezzo = $_GET['prezzounitario'];
        $iva = $_GET['iva'];
        $categoria = $_GET['categoria'];

        echo "<b>ID: </b>$codice <br>";
        echo "<b>Nome: </b>$nome <br>";
        echo "<b>Descrizione: </b>$descrizione <br>";
        echo "<b>Categoria: </b>$categoria <br>";
        echo "<b>Prezzo U: </b>$prezzo <br>";
        echo "<b>IVA: </b>$iva <br>";
    }
    
    ?>
    </div>
  </body>
</html>

La form di filtro

Veniamo alla porzione di esercizio forse più complessa per un alunno alle prime armi col PHP e il filtraggio di un vettore multidimensionale. Prepariamo una piccola formettina in codice html da posizionare prima dell’intestazione della tabella. Qui scegliamo di mettere una tendina ma il discorso potrebbe essere analogo con qualsiasi altra tipologia di input, dalla casella testuale, numerica, radio button ecc.

La form non presenta particolari criticità se non la cosa strana che oltre al method=”post”, la action punti ancora a questa pagina index.php. Una form che invia dati alla stessa pagina in cui si chiama? Concetto un po’ bizzarro ma non così strano da afferrare.

<form method="post" action="index.php">
<label for="cat">Scegli una categoria:</label>
  <select id="cat" name="cat">
    <option value="tutto">Tutto</option>
    <option value="abbigliamento">Abbigliamento</option>
    <option value="alimentari">Alimentari</option>
    <option value="casa">Casa</option>
  </select> 
  <input type="submit" value="Filtra">
</form>

A questo punto dobbiamo creare due filoni di codice: uno prevede che la pagina sia chiamata non dalla form ma dal flusso ordinario del sito web e il secondo flusso che la pagina venga chiamata dalla form con tanto di variabili post inizializzate, nel nostro caso solo quella che contiene il valore scelto della tendina. Verifico quindi se esiste la variabile superglobale $_POST[“cat”] e ne prelevo il valore. A questo punto nel ciclo foreach se la variabile $categoria è valorizzata filtro con un if i valori del vettore, mentre se la variabile categoria non è valorizzata o ha valore “tutto” allora mostro la tabella normale e completa di tutti i dati.

<!doctype html>
<html lang="en">
  <head>
    <meta charset="utf-8">
    <meta name="viewport" content="width=device-width, initial-scale=1">
    <title>Esercizio 00</title>
    <link href="https://cdn.jsdelivr.net/npm/bootstrap@5.3.2/dist/css/bootstrap.min.css" rel="stylesheet" integrity="sha384-T3c6CoIi6uLrA9TneNEoa7RxnatzjcDSCmG1MXxSR1GAsXEV/Dwwykc2MPK8M2HN" crossorigin="anonymous">
  </head>
  <body>
    <div class="container">
    <h1>La mia lista di articoli</h1>

<?php
//voglio creare un vettore associativo di articoli
//li stampa con una tabella graficamente gradevole a righe alternate
//per ogni riga inserisco un link che punta ad un secondo script che mostra i dettagli
//in questa stessa pagina inserisco un filtro per visualizzare in tabella solo un dettaglio come la categoria


$magazzino = 
[
    "ID000" => ["nome"=>"Borsa in pelle", "descrizione"=>"Borsa in pelle da donna in cuoio marrone", "prezzounitario"=>200.50, "iva"=>22, "categoria"=>"abbigliamento"],
    "ID001" => ["nome"=>"Mocassino in cuio", "descrizione"=>"Mocassino in cuoio marrone", "prezzounitario"=>60.00, "iva"=>22, "categoria"=>"abbigliamento"],
    "ID002" => ["nome"=>"Scolapasta elettrico", "descrizione"=>"Scolapasta a pile", "prezzounitario"=>15.90, "iva"=>22, "categoria"=>"casa"],
    "ID003" => ["nome"=>"Cioccolatini misti", "descrizione"=>"Scatola cioccolatini assortiti", "prezzounitario"=>10.00, "iva"=>10, "categoria"=>"alimentari"],
    "ID004" => ["nome"=>"Tazza latte", "descrizione"=>"Tazza cilindrica in ceramica con manico", "prezzounitario"=>6.00, "iva"=>22, "categoria"=>"casa"]
]

?>

<form method="post" action="index.php">
<label for="cat">Scegli una categoria:</label>
  <select id="cat" name="cat">
    <option value="tutto">Tutto</option>
    <option value="abbigliamento">Abbigliamento</option>
    <option value="alimentari">Alimentari</option>
    <option value="casa">Casa</option>
  </select> 
  <input type="submit" value="Filtra">
</form>


<table class="table table-bordered">
<thead>
    <tr>
      <th scope="col">#</th>
      <th scope="col">Nome</th>
      <th scope="col">Descrizione</th>
      <th scope="col">Categoria</th>
      <th scope="col">Dettagli</th>
    </tr>
  </thead>
  <tbody>
<?php
  $indice = 0;

  if (isset($_POST["cat"]))
  {
    $filtro = $_POST["cat"];
    //echo $filtro;
  }  

  foreach ($magazzino as $codice => $articolo)
  {

    $nome = $articolo["nome"];
    $descrizione = $articolo["descrizione"];
    $prezzounitario = $articolo["prezzounitario"];
    $categoria = $articolo["categoria"];


    if ($filtro && $categoria == $filtro)
    {
        if ($indice % 2 == 0)
          echo "<tr class=\"table-secondary\">";
        else
          echo "<tr>";
  
      echo "<td>$codice</td>";
      echo "<td>$nome</td>";
      echo "<td>$descrizione</td>";
      echo "<td>$categoria</td>";
      echo "<td><a href=\"dettaglio.php?id=$codice\">Leggi tutto=></a></td>";
      echo "</tr>";
  
      $indice += 1; 
    }
    
    if (!$filtro || $filtro =="tutto")
    {
      if ($indice % 2 == 0)
        echo "<tr class=\"table-secondary\">";
      else
        echo "<tr>";

      echo "<td>$codice</td>";
      echo "<td>$nome</td>";
      echo "<td>$descrizione</td>";
      echo "<td>$categoria</td>";
      echo "<td><a href=\"dettaglio.php?id=$codice\">Leggi tutto=></a></td>";
      echo "</tr>";

      $indice += 1; 

    }
  }
    
?>

</tbody>  
</table>

Ultima modifica 9 Novembre 2023