In questa lezione impari a
- usare if, elseif, match e i cicli
- lavorare con array indicizzati, associativi e array di array
- generare una tabella HTML con foreach
- scrivere funzioni con parametri e tipi
- dividere il sito in file con require
In questa lezione impariamo gli strumenti con cui, dalla lezione 10, mostreremo i dati del database. Per ora i dati li scriviamo noi in un array; il bello è che il codice resterà quasi identico quando arriveranno da MySQL.
Condizioni
<?php
$disponibili = 1;
if ($disponibili === 0) {
echo 'Non disponibile';
} elseif ($disponibili === 1) {
echo 'Ultima copia!';
} else {
echo "$disponibili copie disponibili";
}
Quando si confronta un valore con tanti casi, PHP 8 ha match, più compatto e più sicuro del vecchio switch (confronta con === e non serve il break):
<?php
$genere = 'Fantascienza';
$icona = match ($genere) {
'Fantascienza' => '🚀',
'Avventura' => '🧭',
'Romanzo', 'Racconti' => '📖',
default => '📚',
};
echo $icona; // 🚀
Ricorda anche il ternario visto nella lezione 7: $testo = $copie > 0 ? 'sì' : 'no';.
Cicli
<?php
// for: quando sai quante volte
for ($i = 1; $i <= 5; $i++) {
echo "Pagina $i ";
}
// while: finché una condizione è vera
$copie = 3;
while ($copie > 0) {
echo "Presto una copia. ";
$copie--;
}
Il ciclo che userai di più però è foreach, che scorre un array: lo vediamo tra poco.
Array
Un array contiene più valori in una sola variabile.
Array indicizzati
<?php
$generi = ['Romanzo', 'Fantascienza', 'Avventura'];
echo $generi[0]; // Romanzo (si parte da 0)
echo count($generi); // 3
$generi[] = 'Racconti'; // aggiunge in fondo
Array associativi
Al posto dei numeri, le posizioni hanno un nome (la chiave). È esattamente come una riga di una tabella:
<?php
$libro = [
'titolo' => 'Io, robot',
'anno' => 1950,
'genere' => 'Fantascienza',
'copie' => 3,
];
echo $libro['titolo']; // Io, robot
echo "Uscito nel {$libro['anno']}";
$libro['copie'] = 4; // modifica
Array di array: le righe di una tabella
Un elenco di libri è un array di array associativi. È proprio la forma in cui, dalla lezione 10, mysqli ci darà il risultato di una SELECT:
<?php
$libri = [
['titolo' => 'Se questo è un uomo', 'autore' => 'Primo Levi', 'anno' => 1947, 'copie' => 4],
['titolo' => 'Il barone rampante', 'autore' => 'Italo Calvino', 'anno' => 1957, 'copie' => 3],
['titolo' => '1984', 'autore' => 'George Orwell', 'anno' => 1949, 'copie' => 5],
['titolo' => 'Frankenstein', 'autore' => 'Mary Shelley', 'anno' => 1818, 'copie' => 2],
];
echo $libri[2]['titolo']; // 1984
foreach
<?php
foreach ($generi as $genere) {
echo "<li>$genere</li>";
}
// con la chiave
foreach ($libro as $campo => $valore) {
echo "$campo: $valore<br>";
}
E ora la cosa più importante della lezione: una tabella HTML generata da un array di righe.
<table>
<tr><th>Titolo</th><th>Autore</th><th>Anno</th><th>Copie</th></tr>
<?php foreach ($libri as $l): ?>
<tr>
<td><?= $l['titolo'] ?></td>
<td><?= $l['autore'] ?></td>
<td><?= $l['anno'] ?></td>
<td><?= $l['copie'] ?></td>
</tr>
<?php endforeach; ?>
</table>
Nota la sintassi alternativa: foreach (...): … endforeach; (e così if (...): … else: … endif;). Dentro l'HTML è molto più leggibile delle graffe, perché si vede subito dove finisce il ciclo.
Funzioni utili sugli array
| Funzione | Cosa fa |
|---|---|
count($a) |
numero di elementi |
in_array('x', $a) |
true se il valore c'è |
array_key_exists('k', $a) o isset($a['k']) |
la chiave esiste? |
sort($a), rsort($a) |
ordina (crescente, decrescente) |
usort($a, fn($x, $y) => $x['anno'] <=> $y['anno']) |
ordina un array di righe per una colonna |
array_column($righe, 'titolo') |
estrae una colonna da un array di righe |
array_sum($a), max($a), min($a) |
somma, massimo, minimo |
implode(', ', $a) |
unisce in una stringa: Romanzo, Fantascienza |
explode(',', $s) |
il contrario: divide una stringa in array |
<?php
$totale = array_sum(array_column($libri, 'copie')); // 14
Funzioni
<?php
function disponibilita(int $copie, int $fuori): string
{
$libere = $copie - $fuori;
if ($libere <= 0) {
return 'non disponibile';
}
return $libere === 1 ? '1 copia' : "$libere copie";
}
echo disponibilita(4, 2); // 2 copie
echo disponibilita(1, 1); // non disponibile
- I tipi dei parametri (
int) e del valore restituito (: string) sono facoltativi, ma aiutano: se passi un tipo sbagliato, PHP te lo dice subito. - Un parametro può avere un valore predefinito:
function saluta(string $nome = 'ospite'). - Le variabili create dentro una funzione non si vedono fuori, e viceversa (si dice che hanno visibilità locale). Quello che serve si passa come parametro.
Alcune funzioni le useremo in tutte le pagine del progetto. Per esempio questa, che mostra una data in italiano:
<?php
function data_it(?string $data): string
{
return $data ? date('d/m/Y', strtotime($data)) : '—';
}
echo data_it('2026-09-29'); // 29/09/2026
echo data_it(null); // —
Il punto interrogativo in ?string significa "una stringa oppure null": è il caso della data_restituzione di un prestito ancora aperto.
include e require: un sito a pezzi
Tutte le pagine di un sito hanno la stessa intestazione, lo stesso menu e lo stesso piè di pagina. Invece di copiarli in ogni file, si scrivono una volta e si includono:
<?php
// header.php
?>
<!DOCTYPE html>
<html lang="it">
<head>
<meta charset="UTF-8">
<meta name="viewport" content="width=device-width, initial-scale=1">
<title><?= $titolo_pagina ?? 'Biblioteca' ?></title>
<link rel="stylesheet" href="stile.css">
</head>
<body>
<header>
<a href="index.php">📚 Biblioteca</a>
<nav><a href="index.php">Catalogo</a> <a href="prestiti.php">Prestiti</a></nav>
</header>
<main>
<?php
// footer.php
?>
</main>
<footer>Biblioteca dell'I.I.S. Primo Levi</footer>
</body>
</html>
E ogni pagina diventa corta:
<?php
$titolo_pagina = 'Catalogo';
require 'header.php';
?>
<h1>Catalogo</h1>
<p>Qui arriverà l'elenco dei libri.</p>
<?php require 'footer.php'; ?>
| Istruzione | Se il file non c'è… |
|---|---|
include 'f.php' |
avviso (warning), la pagina continua |
require 'f.php' |
errore fatale, la pagina si ferma |
require_once 'f.php' |
come require, ma se il file è già stato incluso non lo include una seconda volta |
Per i file indispensabili (configurazione, connessione al database, funzioni) si usa sempre require_once: senza di loro la pagina non ha senso, ed è meglio fermarsi subito che andare avanti a metà.
Il file incluso vede le variabili della pagina che lo include: per questo
header.phppuò usare$titolo_pagina.
Esercizi
Esercizio 1 – Il catalogo finto. Crea catalogo.php con l'array $libri di questa lezione (aggiungi almeno altri due libri) e mostra una tabella con titolo, autore, anno, copie e una colonna Età che dice "classico" se il libro ha più di 100 anni, "moderno" altrimenti. Sotto la tabella scrivi il totale delle copie.
Mostra la soluzione
<?php
$libri = [
['titolo' => 'Se questo è un uomo', 'autore' => 'Primo Levi', 'anno' => 1947, 'copie' => 4],
['titolo' => 'Il barone rampante', 'autore' => 'Italo Calvino', 'anno' => 1957, 'copie' => 3],
['titolo' => '1984', 'autore' => 'George Orwell', 'anno' => 1949, 'copie' => 5],
['titolo' => 'Frankenstein', 'autore' => 'Mary Shelley', 'anno' => 1818, 'copie' => 2],
['titolo' => 'Io, robot', 'autore' => 'Isaac Asimov', 'anno' => 1950, 'copie' => 3],
['titolo' => 'Ventimila leghe sotto i mari', 'autore' => 'Jules Verne', 'anno' => 1870, 'copie' => 2],
];
$anno_corrente = (int) date('Y');
?>
<!DOCTYPE html>
<html lang="it">
<head><meta charset="UTF-8"><title>Catalogo</title></head>
<body>
<h1>Catalogo</h1>
<table border="1">
<tr><th>Titolo</th><th>Autore</th><th>Anno</th><th>Copie</th><th>Età</th></tr>
<?php foreach ($libri as $l): ?>
<tr>
<td><?= $l['titolo'] ?></td>
<td><?= $l['autore'] ?></td>
<td><?= $l['anno'] ?></td>
<td><?= $l['copie'] ?></td>
<td><?= $anno_corrente - $l['anno'] > 100 ? 'classico' : 'moderno' ?></td>
</tr>
<?php endforeach; ?>
</table>
<p>Copie totali: <?= array_sum(array_column($libri, 'copie')) ?></p>
</body>
</html>
Le copie totali sono 19. Frankenstein e Ventimila leghe risultano "classico".
Esercizio 2 – Filtra e ordina. Aggiungi in cima a catalogo.php il codice per mostrare solo i libri usciti dopo il 1900, ordinati dal più recente. Usa un foreach con un if, oppure array_filter, e usort.
Mostra la soluzione
<?php
// versione con foreach
$moderni = [];
foreach ($libri as $l) {
if ($l['anno'] > 1900) {
$moderni[] = $l;
}
}
// la stessa cosa con array_filter
$moderni = array_filter($libri, fn($l) => $l['anno'] > 1900);
// dal più recente: b confrontato con a
usort($moderni, fn($a, $b) => $b['anno'] <=> $a['anno']);
Poi nel foreach della tabella si usa $moderni al posto di $libri. L'operatore <=> (astronave) restituisce -1, 0 o 1, che è proprio quello che usort vuole.
Fra qualche lezione questo lavoro lo farà il database con WHERE anno > 1900 ORDER BY anno DESC: è molto più efficiente, perché dal database arrivano solo le righe che servono.
Esercizio 3 – Il sito a pezzi. Crea header.php, footer.php e due pagine, index.php (il catalogo dell'esercizio 1) e info.php (orari della biblioteca), che li includono. Ogni pagina deve avere il suo titolo nella scheda del browser. Aggiungi poi un file funzioni.php con la funzione data_it() e usala in info.php per scrivere la data di oggi.
Mostra la soluzione
header.php e footer.php sono quelli della lezione. Le pagine:
<?php
// info.php
require_once 'funzioni.php';
$titolo_pagina = 'Orari';
require 'header.php';
?>
<h1>Orari della biblioteca</h1>
<p>Dal lunedì al venerdì, dalle 10 alle 13.</p>
<p>Oggi è il <?= data_it(date('Y-m-d')) ?>.</p>
<?php require 'footer.php'; ?>
<?php
// funzioni.php
function data_it(?string $data): string
{
return $data ? date('d/m/Y', strtotime($data)) : '—';
}
Se cambi una voce del menu in header.php, cambia in tutte le pagine. È la stessa organizzazione dell'applicazione finale del corso.