4E e 4I SIA: procedura completa con php e file di testo, login, session, md5, captcha, le librerie Leaflet e Leaflet Routing Machine
Relazione sulla Procedura di Gestione delle Prenotazioni e Consegne
(compreso gli script di ogni pagina e la spiegazione riga per riga del codice.
In fondo al post ci sono altre due pagine php che consentono di salvare i dati di consegna della merce compreso le coordinate geografiche in un file di testo)
link per scaricare l'intera procedura
Introduzione
La procedura
descritta consiste in un sistema di gestione delle prenotazioni e consegne per
una paninoteca, implementato in PHP. Utilizza file di testo per memorizzare le
informazioni degli utenti e le prenotazioni. La procedura include funzionalità
di registrazione e login, gestione delle sessioni, validazione attraverso
CAPTCHA, crittografia delle password con MD5 e utilizzo di librerie JavaScript
come Leaflet per il tracciamento delle consegne.
Componenti
Principali
1.
**Gestione delle Sessioni**
- Il sistema utilizza la funzione
`session_start()` per avviare o riprendere una sessione. Le sessioni sono
impiegate per mantenere lo stato dell'utente (loggato o meno) e per gestire le
autorizzazioni (ad esempio, se l'utente è un amministratore).
2.
**Registrazione e Login**
- Gli utenti possono registrarsi fornendo un
nome utente e una password. La password è crittografata utilizzando l'algoritmo
MD5 prima di essere salvata in un file di testo (`users.txt`). Durante il
login, le credenziali inserite vengono verificate confrontando i dati forniti
con quelli memorizzati nel file.
- Un CAPTCHA è generato e mostrato
all'utente per prevenire accessi automatizzati e attacchi di tipo brute-force.
Questo CAPTCHA viene aggiornato ad ogni tentativo di login.
3.
**Gestione delle Prenotazioni**
- Le prenotazioni sono memorizzate in un
file di testo (`bookings.txt`). Gli utenti possono visualizzare, modificare e
cancellare le proprie prenotazioni. L'amministratore ha accesso a tutte le
prenotazioni e può gestirle tramite un'interfaccia web.
- Le modifiche alle prenotazioni sono
implementate attraverso l'invio di un modulo HTML, che aggiorna il file di
prenotazioni e reindirizza l'utente alla pagina di gestione.
4.
**Utilizzo delle Librerie Leaflet**
- Leaflet è utilizzato per visualizzare una
mappa interattiva nel contesto della gestione delle consegne. Gli utenti
possono inserire un indirizzo di destinazione e un oggetto da consegnare. Il
sistema utilizza un servizio di geocodifica (Nominatim) per convertire
l'indirizzo in coordinate geografiche.
- Una volta ottenute le coordinate, il
sistema traccia il percorso sulla mappa e simula il movimento di un
"camion" da un punto di partenza (la paninoteca) all'indirizzo di
destinazione. Durante questo processo, un messaggio di conferma viene mostrato
all'utente al termine della consegna.
5.
**Sicurezza e Validazione**
- Per garantire la sicurezza, la validazione
degli input è essenziale. Le credenziali utente e gli indirizzi sono
controllati per prevenire errori e attacchi informatici.
- I dati provenienti dagli utenti sono
trattati utilizzando `htmlspecialchars()` per prevenire attacchi di tipo XSS
(Cross-Site Scripting).
6.
**Funzionalità di Logout**
- Gli utenti possono disconnettersi attraverso
un semplice script che distrugge la sessione corrente e reindirizza alla pagina
di login.
Conclusioni
Il sistema
descritto offre una soluzione completa per la gestione delle prenotazioni e
delle consegne di una paninoteca. Attraverso l'uso di PHP e file di testo,
fornisce funzionalità essenziali come registrazione, login, gestione delle
prenotazioni e tracciamento delle consegne. L'integrazione di CAPTCHA e MD5
contribuisce a garantire la sicurezza del sistema, mentre l'uso della libreria
Leaflet arricchisce l'esperienza utente con funzionalità interattive. Questo
approccio, sebbene semplice, dimostra come si possano implementare sistemi di
gestione pratici e sicuri utilizzando tecnologie web comuni.
<?php
session_start();
return rand(1000, 9999);
}
function validateUser($username, $password) {
$users = file('users.txt', FILE_IGNORE_NEW_LINES);
foreach ($users as $user) {
list($fileUser, $filePassword) = explode(':', $user);
if ($fileUser == $username && $filePassword == md5($password)) {
return true;
}
}
return false;
}
function validateAdmin($username, $password) {
return validateUser($username, $password) && $username === 'admin';
}
// Genera un nuovo CAPTCHA se non esiste già
if (!isset($_SESSION['captcha'])) {
$_SESSION['captcha'] = generateCaptcha();
}
// Gestione del login
if ($_SERVER['REQUEST_METHOD'] == 'POST') {
$username = $_POST['username'];
$password = $_POST['password'];
$role = $_POST['role'];
$captcha = $_POST['captcha'];
if ($_SESSION['captcha'] == $captcha) {
if ($role == 'user' && validateUser($username, $password)) {
$_SESSION['username'] = $username;
header("Location: booking.php");
exit;
} elseif ($role == 'admin' && validateAdmin($username, $password)) {
$_SESSION['admin'] = true;
header("Location: view_bookings.php");
exit;
} else {
$error = "Credenziali non valide!";
}
} else {
$error = "Captcha errato!";
}
// Aggiorna sempre il CAPTCHA dopo un tentativo di login
$_SESSION['captcha'] = generateCaptcha();
}
?>
<!DOCTYPE html>
<html>
<head>
<title>Login Paninoteca</title>
</head>
<body>
<h2>Login</h2>
<?php if (isset($error)) echo "<p style='color:red;'>$error</p>"; ?>
<form method="post">
<label>Username:</label>
<input type="text" name="username" required><br>
<label>Password:</label>
<input type="password" name="password" required><br>
<label>Ruolo:</label>
<select name="role">
<option value="user">Utente</option>
<option value="admin">Paninoteca</option>
</select><br>
<label>Captcha:</label> <?php echo $_SESSION['captcha']; ?><br>
<input type="text" name="captcha" required><br>
<input type="submit" value="Accedi">
</form>
<p><a href="register.php">Registrati come Utente</a></p>
<p><a href="register_admin.php">Registrati come Paninoteca</a></p>
<p><a href="logout.php">Logout</a></p> <!-- Link per il logout -->
</body>
</html>
Spiegazione del codice della pagina index.php
<?php
session_start();
- **`session_start();`**: Avvia una nuova sessione o riprende una sessione esistente. Questo è necessario per memorizzare informazioni tra diverse pagine.
function generateCaptcha() {
return rand(1000, 9999);
}
- **`function generateCaptcha()`**: Definisce una funzione che genera un numero casuale tra 1000 e 9999.
- **`return rand(1000, 9999);`**: Restituisce un numero casuale, che funge da CAPTCHA.
function validateUser($username, $password) {
$users = file('users.txt', FILE_IGNORE_NEW_LINES);
- **`function validateUser($username, $password)`**: Definisce una funzione per validare le credenziali di un utente.
- **`$users = file('users.txt', FILE_IGNORE_NEW_LINES);`**: Legge il file `users.txt` e memorizza ogni riga in un array, ignorando le nuove righe.
foreach ($users as $user) {
list($fileUser, $filePassword) = explode(':', $user);
- **`foreach ($users as $user)`**: Itera attraverso ciascun elemento dell'array `$users`.
- **`list($fileUser, $filePassword) = explode(':', $user);`**: Divide ogni riga in due parti, assegnando il nome utente e la password a `$fileUser` e `$filePassword`.
if ($fileUser == $username && $filePassword == md5($password)) {
return true;
}
}
return false;
}
- **`if ($fileUser == $username && $filePassword == md5($password))`**: Controlla se il nome utente corrisponde e se la password, criptata in MD5, corrisponde a quella nel file.
- **`return true;`**: Restituisce `true` se le credenziali sono valide.
- **`return false;`**: Restituisce `false` se le credenziali non corrispondono.
function validateAdmin($username, $password) {
return validateUser($username, $password) && $username === 'admin';
}
- **`function validateAdmin($username, $password)`**: Definisce una funzione per validare se l'utente è un amministratore.
- **`return validateUser($username, $password) && $username === 'admin';`**: Restituisce `true` se le credenziali sono valide e se l'username è 'admin'.
if (!isset($_SESSION['captcha'])) {
$_SESSION['captcha'] = generateCaptcha();
- **`if (!isset($_SESSION['captcha']))`**: Controlla se il CAPTCHA non è già stato impostato nella sessione.
- **`$_SESSION['captcha'] = generateCaptcha();`**: Se non esiste, genera un nuovo CAPTCHA e lo memorizza nella sessione.
if ($_SERVER['REQUEST_METHOD'] == 'POST') {
- **`if ($_SERVER['REQUEST_METHOD'] == 'POST')`**: Verifica se il modulo è stato inviato tramite il metodo POST.
$username = $_POST['username'];
$password = $_POST['password'];
$role = $_POST['role'];
$captcha = $_POST['captcha'];
- Queste righe recuperano il nome utente, la password, il ruolo e il CAPTCHA inserito dall'utente dal modulo HTML.
if ($_SESSION['captcha'] == $captcha) {
- **`if ($_SESSION['captcha'] == $captcha)`**: Controlla se il CAPTCHA inserito dall'utente corrisponde a quello salvato nella sessione.
if ($role == 'user' && validateUser($username, $password)) {
$_SESSION['username'] = $username;
header("Location: booking.php");
exit;
} elseif ($role == 'admin' && validateAdmin($username, $password)) {
$_SESSION['admin'] = true;
header("Location: view_bookings.php");
exit;
} else {
$error = "Credenziali non valide!";
}
- Se il CAPTCHA è corretto:
- Controlla se il ruolo è 'user' e le credenziali sono valide. Se sì, memorizza il nome utente nella sessione e reindirizza a `booking.php`.
- Se il ruolo è 'admin' e le credenziali sono valide, imposta una variabile di sessione per l'amministratore e reindirizza a `view_bookings.php`.
- Se le credenziali non sono valide, imposta un messaggio di errore.
} else {
$error = "Captcha errato!";
}
- Se il CAPTCHA è errato, imposta un messaggio di errore.
$_SESSION['captcha'] = generateCaptcha();
}
- Aggiorna sempre il CAPTCHA dopo un tentativo di login, sia esso riuscito o fallito.
<!DOCTYPE html>
<html>
<head>
<title>Login Paninoteca</title>
</head>
<body>
<h2>Login</h2>
- Questa parte inizia la struttura HTML della pagina, specificando che si tratta di un documento HTML5. Viene impostato il titolo della pagina.
<?php if (isset($error)) echo "<p style='color:red;'>$error</p>"; ?>
- Se c'è un errore di login, viene visualizzato in rosso.
<form method="post">
<label>Username:</label>
<input type="text" name="username" required><br>
<label>Password:</label>
<input type="password" name="password" required><br>
<label>Ruolo:</label>
<select name="role">
<option value="user">Utente</option>
<option value="admin">Paninoteca</option>
</select><br>
<label>Captcha:</label> <?php echo $_SESSION['captcha']; ?><br>
<input type="text" name="captcha" required><br>
<input type="submit" value="Accedi">
</form>
- Qui viene creato un modulo per il login. Include campi per l'username, password, ruolo e CAPTCHA. L'utente deve compilare tutti i campi per inviare il modulo.
<p><a href="register.php">Registrati come Utente</a></p>
<p><a href="register_admin.php">Registrati come Paninoteca</a></p>
<p><a href="logout.php">Logout</a></p> <!-- Link per il logout -->
</body>
</html>
- Questi paragrafi offrono link per registrarsi come utente o amministratore, e un link per il logout. La pagina termina qui.
Considerazioni Finali
Questo codice offre un sistema di autenticazione di base.
Pagina register.php
<?php
session_start();
// Funzione
per generare un captcha
function
generateCaptcha() {
return rand(1000, 9999);
}
// Gestione
della registrazione
if
($_SERVER['REQUEST_METHOD'] == 'POST') {
$username = $_POST['username'];
$password = md5($_POST['password']);
$captcha = $_POST['captcha'];
if ($_SESSION['captcha'] == $captcha) {
// Salva l'utente in un file di testo
$userData =
"$username:$password\n";
file_put_contents('users.txt',
$userData, FILE_APPEND);
echo "Registrazione avvenuta con
successo!";
} else {
echo "Captcha errato!";
}
}
// Genera un
nuovo captcha
$_SESSION['captcha']
= generateCaptcha();
?>
<!DOCTYPE
html>
<html>
<head>
<title>Registrazione</title>
</head>
<body>
<h2>Registrazione</h2>
<form method="post">
Username: <input
type="text" name="username" required><br>
Password: <input
type="password" name="password" required><br>
Captcha: <?php echo
$_SESSION['captcha']; ?><br>
<input type="text"
name="captcha" required><br>
<input type="submit"
value="Registrati">
</form>
<p><a href="index.php">Torna
al login</a></p>
</body>
</html>
Spiegazione del codice della pagina
register.php
Ecco una
spiegazione riga per riga del codice PHP e HTML che hai fornito, che implementa
un sistema di registrazione per utenti.
<?php
session_start();
-
**`session_start();`**: Avvia una nuova sessione o riprende una sessione
esistente, permettendo di memorizzare informazioni tra diverse pagine.
// Funzione
per generare un captcha
function
generateCaptcha() {
return rand(1000, 9999);
}
-
**`function generateCaptcha()`**: Definisce una funzione che genera un numero
casuale tra 1000 e 9999 da usare come CAPTCHA.
- **`return
rand(1000, 9999);`**: Restituisce un numero casuale, che funge da CAPTCHA.
// Gestione
della registrazione
if
($_SERVER['REQUEST_METHOD'] == 'POST') {
- **`if
($_SERVER['REQUEST_METHOD'] == 'POST')`**: Controlla se il modulo è stato
inviato con il metodo POST. Se sì, esegue il codice seguente per gestire la
registrazione.
$username = $_POST['username'];
$password = md5($_POST['password']);
$captcha = $_POST['captcha'];
-
**`$username = $_POST['username'];`**: Recupera il nome utente inserito nel
modulo.
-
**`$password = md5($_POST['password']);`**: Recupera la password, la cripta
usando l'algoritmo MD5 (anche se MD5 non è raccomandato per la sicurezza delle
password).
-
**`$captcha = $_POST['captcha'];`**: Recupera il CAPTCHA inserito dall'utente.
if ($_SESSION['captcha'] == $captcha) {
- **`if
($_SESSION['captcha'] == $captcha)`**: Controlla se il CAPTCHA inserito
dall'utente corrisponde a quello memorizzato nella sessione.
// Salva l'utente in un file di testo
$userData =
"$username:$password\n";
file_put_contents('users.txt',
$userData, FILE_APPEND);
echo "Registrazione avvenuta con
successo!";
```
-
**`$userData = "$username:$password\n";`**: Prepara la stringa con il
nome utente e la password, separati da due punti e seguiti da una nuova riga.
-
**`file_put_contents('users.txt', $userData, FILE_APPEND);`**: Scrive i dati
dell'utente nel file `users.txt`, aggiungendoli alla fine del file senza
sovrascrivere i dati esistenti.
- **`echo
"Registrazione avvenuta con successo!";`**: Mostra un messaggio di
conferma della registrazione.
} else {
echo "Captcha errato!";
}
}
- **`else {
echo "Captcha errato!"; }`**: Se il CAPTCHA è errato, mostra un
messaggio di errore.
// Genera un
nuovo captcha
$_SESSION['captcha']
= generateCaptcha();
-
**`$_SESSION['captcha'] = generateCaptcha();`**: Genera un nuovo CAPTCHA e lo
memorizza nella sessione, così ogni volta che la pagina viene caricata o
ricaricata, viene fornito un nuovo CAPTCHA.
<!DOCTYPE
html>
<html>
<head>
<title>Registrazione</title>
</head>
<body>
<h2>Registrazione</h2>
- Questa
parte inizia la struttura HTML della pagina, specificando che si tratta di un
documento HTML5. Imposta il titolo della pagina come "Registrazione".
<form method="post">
Username: <input
type="text" name="username" required><br>
Password: <input
type="password" name="password" required><br>
Captcha: <?php echo
$_SESSION['captcha']; ?><br>
<input type="text"
name="captcha" required><br>
<input type="submit"
value="Registrati">
</form>
- Viene
creato un modulo per la registrazione con i seguenti campi:
- **Username**: Un campo di input di testo
per il nome utente.
- **Password**: Un campo di input di password
per la password.
- **Captcha**: Mostra il CAPTCHA generato.
- **Captcha input**: Un campo di input di
testo per inserire il CAPTCHA.
- **Submit button**: Un pulsante per inviare
il modulo.
<p><a
href="index.php">Torna al login</a></p>
</body>
</html>
- Questi
paragrafi offrono un link per tornare alla pagina di login. La pagina termina
qui.
Considerazioni
Finali
Questo
codice fornisce una registrazione di base degli utenti.
Pagina register_admin.php
<?php
session_start();
function
generateCaptcha() {
return rand(1000, 9999);
}
// Genera un
nuovo captcha se non esiste già
if
(!isset($_SESSION['captcha'])) {
$_SESSION['captcha'] = generateCaptcha();
}
if
($_SERVER['REQUEST_METHOD'] == 'POST') {
$username = $_POST['username'];
$password = md5($_POST['password']); //
Password criptata
$captcha = $_POST['captcha'];
// Salva il nuovo utente nel file
users.txt
file_put_contents('users.txt',
"$username:$password\n", FILE_APPEND);
echo "Registrazione avvenuta con
successo!";
unset($_SESSION['captcha']); // Resetta
il captcha
} else {
$error = "Captcha errato!";
}
}
?>
<!DOCTYPE
html>
<html>
<head>
<title>Registrazione
Paninoteca</title>
</head>
<body>
<h2>Registrazione Personale
Paninoteca</h2>
<?php if (isset($error)) echo
"<p style='color:red;'>$error</p>"; ?>
<form method="post">
Username: <input
type="text" name="username" required><br>
Password: <input
type="password" name="password" required><br>
Captcha: <?php echo
$_SESSION['captcha']; ?><br>
<input type="text"
name="captcha" required><br>
<input type="submit"
value="Registrati">
</form>
<p><a
href="index.php">Torna al login</a></p>
</body>
</html>
Spiegazione della Pagina register_admin.php
<?php
session_start();
function
generateCaptcha() {
return rand(1000, 9999);
}
// Genera un
nuovo captcha se non esiste già
if
(!isset($_SESSION['captcha'])) {
$_SESSION['captcha'] = generateCaptcha();
}
if
($_SERVER['REQUEST_METHOD'] == 'POST') {
$username = $_POST['username'];
$password = md5($_POST['password']); //
Password criptata
$captcha = $_POST['captcha'];
if ($_SESSION['captcha'] == $captcha) {
// Salva il nuovo utente nel file
users.txt
file_put_contents('users.txt',
"$username:$password\n", FILE_APPEND);
echo "Registrazione avvenuta con
successo!";
unset($_SESSION['captcha']); // Resetta
il captcha
} else {
$error = "Captcha errato!";
}
}
?>
<!DOCTYPE
html>
<html>
<head>
<title>Registrazione
Paninoteca</title>
</head>
<body>
<h2>Registrazione Personale
Paninoteca</h2>
<?php if (isset($error)) echo
"<p style='color:red;'>$error</p>"; ?>
<form method="post">
Username: <input
type="text" name="username" required><br>
Password: <input
type="password" name="password" required><br>
Captcha: <?php echo
$_SESSION['captcha']; ?><br>
<input type="text"
name="captcha" required><br>
<input type="submit"
value="Registrati">
</form>
<p><a
href="index.php">Torna al login</a></p>
</body>
</html>
Pagina delivery.php
<!DOCTYPE
html>
<html
lang="it">
<head>
<meta charset="UTF-8">
<meta name="viewport"
content="width=device-width, initial-scale=1.0">
<title>Consegna a Lodi</title>
<link rel="stylesheet"
href="https://unpkg.com/leaflet/dist/leaflet.css" />
<link rel="stylesheet"
href="https://unpkg.com/leaflet-routing-machine/dist/leaflet-routing-machine.css"
/>
<style>
#map { height: 400px; width: 100%; }
#consegna { display: none; font-size:
20px; color: green; }
</style>
</head>
<body>
<h1>Tracciamento Consegna a
Lodi</h1>
<form id="form">
<label
for="indirizzo">Indirizzo e Numero Civico:</label>
<input type="text"
id="indirizzo" placeholder="es: Viale Pavia 28, Lodi"
required>
<label
for="oggetto">Oggetto da Consegnare:</label>
<input type="text" id="oggetto"
placeholder="Descrivi l'oggetto" required>
<button
type="submit">Traccia Percorso</button>
</form>
<div id="map"></div>
<div id="consegna">✅
Consegna avvenuta!</div>
<script
src="https://unpkg.com/leaflet/dist/leaflet.js"></script>
<script
src="https://unpkg.com/leaflet-routing-machine/dist/leaflet-routing-machine.js"></script>
<script>
const partenza = [45.3167, 9.5000]; //
Coordinate della paninoteca
const map = L.map('map').setView(partenza,
13);
L.tileLayer('https://{s}.tile.openstreetmap.org/{z}/{x}/{y}.png', {
maxZoom: 19 }).addTo(map);
const routingControl =
L.Routing.control({ waypoints: [], routeWhileDragging: true }).addTo(map);
document.getElementById('form').onsubmit
= async function(e) {
e.preventDefault();
const indirizzo =
document.getElementById('indirizzo').value;
const oggetto =
document.getElementById('oggetto').value;
// Geocodifica dell'indirizzo
const geoUrl =
`https://nominatim.openstreetmap.org/search?q=${encodeURIComponent(indirizzo)}&format=json&addressdetails=1`;
try {
const response = await
fetch(geoUrl);
const data = await
response.json();
if (data.length === 0) {
alert('Indirizzo non
trovato. Assicurati di inserire un indirizzo valido.');
return;
}
const destinazione =
[data[0].lat, data[0].lon];
routingControl.setWaypoints([L.latLng(partenza[0], partenza[1]),
L.latLng(destinazione[0], destinazione[1])]);
const icon = L.icon({ iconUrl:
'https://img.icons8.com/ios-filled/50/000000/truck.png', iconSize: [32, 32] });
const truckMarker =
L.marker(partenza, { icon }).addTo(map);
routingControl.on('routesfound', function(e) {
const route = e.routes[0];
let index = 0;
const moveTruck = () =>
{
if (index <
route.coordinates.length) {
truckMarker.setLatLng(route.coordinates[index++]);
setTimeout(moveTruck,
100);
} else {
// Mostra il
messaggio di consegna con indirizzo e oggetto
document.getElementById('consegna').innerHTML = `✅ Consegna avvenuta a
${indirizzo} con oggetto: ${oggetto}!`;
document.getElementById('consegna').style.display = 'block';
}
};
moveTruck();
});
} catch (error) {
alert('Si è verificato un
errore durante la geocodifica. Riprova più tardi.');
}
};
</script>
</body>
</html>
Spiegazione della pagina delivery.php
<!DOCTYPE
html>
<html
lang="it">
-
**`<!DOCTYPE html>`**: Indica che il documento è un file HTML5.
-
**`<html lang="it">`**: Inizia il documento HTML e specifica
che la lingua principale del contenuto è l'italiano.
<head>
<meta charset="UTF-8">
<meta name="viewport"
content="width=device-width, initial-scale=1.0">
<title>Consegna a Lodi</title>
-
**`<head>`**: Contiene metadati e collegamenti a risorse esterne.
- **`<meta
charset="UTF-8">`**: Imposta la codifica dei caratteri su UTF-8.
-
**`<meta name="viewport" content="width=device-width,
initial-scale=1.0">`**: Imposta le dimensioni della viewport per
garantire che il sito sia reattivo su dispositivi mobili.
- **`<title>Consegna
a Lodi</title>`**: Imposta il titolo della pagina che appare nella scheda
del browser.
<link rel="stylesheet"
href="https://unpkg.com/leaflet/dist/leaflet.css" />
<link rel="stylesheet"
href="https://unpkg.com/leaflet-routing-machine/dist/leaflet-routing-machine.css"
/>
-
**`<link rel="stylesheet">`**: Collega i fogli di stile CSS
necessari per Leaflet e Leaflet Routing Machine, che sono librerie per la mappatura.
<style>
#map { height: 400px; width: 100%; }
#consegna { display: none; font-size:
20px; color: green; }
</style>
</head>
-
**`<style>`**: Sezione per stili CSS personalizzati.
- **`#map { height: 400px; width: 100%; }`**:
Imposta l'altezza della mappa a 400 pixel e la larghezza al 100% del
contenitore.
- **`#consegna { display: none; font-size:
20px; color: green; }`**: Nasconde inizialmente il messaggio di conferma della
consegna.
<body>
<h1>Tracciamento Consegna a
Lodi</h1>
-
**`<body>`**: Inizio del contenuto visibile della pagina.
-
**`<h1>Tracciamento Consegna a Lodi</h1>`**: Intestazione
principale della pagina.
<form id="form">
<label
for="indirizzo">Indirizzo e Numero Civico:</label>
<input type="text"
id="indirizzo" placeholder="es: Viale Pavia 28, Lodi"
required>
<label
for="oggetto">Oggetto da Consegnare:</label>
<input type="text"
id="oggetto" placeholder="Descrivi l'oggetto" required>
<button
type="submit">Traccia Percorso</button>
</form>
-
**`<form id="form">`**: Definisce un modulo per l'inserimento
dei dati. L'ID permette di identificarlo nel JavaScript.
-
**`<label>`**: Fornisce un'etichetta per ogni campo di input, migliorando
l'accessibilità.
-
**`<input type="text" id="indirizzo" required>`**:
Campo di input per l'indirizzo, con un messaggio di esempio.
-
**`<input type="text" id="oggetto" required>`**:
Campo di input per descrivere l'oggetto da consegnare.
-
**`<button type="submit">Traccia Percorso</button>`**:
Pulsante per inviare il modulo.
<div id="map"></div>
<div id="consegna">✅
Consegna avvenuta!</div>
- **`<div
id="map"></div>`**: Contenitore per la mappa, dove verrà
visualizzata.
- **`<div
id="consegna">✅ Consegna avvenuta!</div>`**: Contenitore per
il messaggio di conferma della consegna, inizialmente nascosto.
<script src="https://unpkg.com/leaflet/dist/leaflet.js"></script>
<script
src="https://unpkg.com/leaflet-routing-machine/dist/leaflet-routing-machine.js"></script>
-
**`<script>`**: Collega i file JavaScript necessari per Leaflet e Leaflet
Routing Machine, per la gestione delle mappe e delle rotte.
<script>
const partenza = [45.3167, 9.5000]; //
Coordinate della paninoteca
const map =
L.map('map').setView(partenza, 13);
- **`const
partenza = [45.3167, 9.5000];`**: Definisce le coordinate della paninoteca.
- **`const
map = L.map('map').setView(partenza, 13);`**: Inizializza la mappa centrata
sulle coordinate di partenza con un livello di zoom di 13.
L.tileLayer('https://{s}.tile.openstreetmap.org/{z}/{x}/{y}.png',
{ maxZoom: 19 }).addTo(map);
-
**`L.tileLayer(...)`**: Aggiunge un layer di tiles alla mappa, utilizzando
OpenStreetMap come fonte. Imposta il massimo livello di zoom a 19.
const routingControl =
L.Routing.control({ waypoints: [], routeWhileDragging: true }).addTo(map);
- **`const
routingControl = L.Routing.control(...)`**: Crea un controllo per la
navigazione, inizialmente senza waypoint, permettendo di aggiornare il percorso
mentre si trascinano i punti sulla mappa.
document.getElementById('form').onsubmit = async function(e) {
e.preventDefault();
-
**`document.getElementById('form').onsubmit = async function(e)`**: Imposta una
funzione da eseguire quando il modulo viene inviato.
-
**`e.preventDefault();`**: Previene il comportamento predefinito del modulo
(cioè, il ricaricamento della pagina).
const indirizzo =
document.getElementById('indirizzo').value;
const oggetto =
document.getElementById('oggetto').value;
- **`const
indirizzo = document.getElementById('indirizzo').value;`**: Recupera il valore
dell'indirizzo inserito.
- **`const
oggetto = document.getElementById('oggetto').value;`**: Recupera il valore
dell'oggetto da consegnare.
// Geocodifica dell'indirizzo
const geoUrl =
`https://nominatim.openstreetmap.org/search?q=${encodeURIComponent(indirizzo)}&format=json&addressdetails=1`;
- **`const
geoUrl = ...`**: Crea un URL per la geocodifica dell'indirizzo, utilizzando
l'API di Nominatim di OpenStreetMap. `encodeURIComponent(indirizzo)` codifica
l'indirizzo per l'URL.
try {
const response = await fetch(geoUrl);
const data = await
response.json();
- **`try {
... } catch (error) { ... }`**: Struttura di gestione degli errori. Tenta di
eseguire il blocco di codice all'interno di `try`.
- **`const
response = await fetch(geoUrl);`**: Effettua una richiesta HTTP per ottenere i
dati geocodificati dall'URL creato.
- **`const
data = await response.json();`**: Converte la risposta in formato JSON.
if (data.length === 0) {
alert('Indirizzo non trovato.
Assicurati di inserire un indirizzo valido.');
return;
}
- **`if
(data.length === 0) { ... }`**: Controlla se non ci sono risultati per
l'indirizzo cercato. Se non ci sono risultati, mostra un avviso e termina l'esecuzione
della funzione.
const destinazione =
[data[0].lat, data[0].lon];
routingControl.setWaypoints([L.latLng(partenza[0],
partenza[1]), L.latLng(destinazione[0], destinazione[1])]);
- **`const
destinazione = [data[0].lat, data[0].lon];`**: Estrae le coordinate della prima
corrispondenza dell'indirizzo trovato.
-
**`routingControl.setWaypoints([...])`**: Imposta i waypoint per il routing,
utilizzando le coordinate di partenza e destinazione.
const icon = L.icon({ iconUrl:
'https://img.icons8.com/ios-filled/50/000000/truck
.png',
iconSize: [32, 32] });
const truckMarker =
L.marker(partenza, { icon }).addTo(map);
- **`const
icon = L.icon({...})`**: Crea un'icona personalizzata per il marker del camion.
- **`const
truckMarker = L.marker(partenza, { icon }).addTo(map);`**: Aggiunge un marker
alla mappa posizionato all'indirizzo di partenza utilizzando l'icona definita.
routingControl.on('routesfound',
function(e) {
const route = e.routes[0];
-
**`routingControl.on('routesfound', function(e) { ... })`**: Aggiunge un evento
che si attiva quando vengono trovati i percorsi. La variabile `e` contiene i
dettagli del percorso trovato.
- **`const
route = e.routes[0];`**: Prende il primo percorso dalla risposta.
let index = 0;
const moveTruck = () =>
{
if (index <
route.coordinates.length) {
truckMarker.setLatLng(route.coordinates[index++]);
setTimeout(moveTruck, 100);
} else {
- **`let
index = 0;`**: Inizializza un indice per il percorso.
- **`const
moveTruck = () => { ... }`**: Definisce una funzione per spostare il marker
del camion lungo il percorso.
- **`if
(index < route.coordinates.length) { ... }`**: Controlla se ci sono ancora
coordinate da percorrere. Se sì, sposta il marker.
// Mostra il messaggio di consegna con
indirizzo e oggetto
document.getElementById('consegna').innerHTML = `✅ Consegna avvenuta a
${indirizzo} con oggetto: ${oggetto}!`;
document.getElementById('consegna').style.display
= 'block';
}
};
moveTruck();
- **`//
Mostra il messaggio di consegna...`**: Quando il camion ha raggiunto la destinazione,
aggiorna il messaggio di conferma con l'indirizzo e l'oggetto.
-
**`document.getElementById('consegna').style.display = 'block';`**: Rende
visibile il messaggio di conferma.
});
} catch (error) {
alert('Si è verificato un errore durante
la geocodifica. Riprova più tardi.');
}
};
</script>
</body>
</html>
- **`});`**:
Chiude l'evento `on('routesfound')`.
- **`catch
(error) { ... }`**: Gestisce eventuali errori durante la geocodifica, mostrando
un messaggio di errore.
-
**`</script>`**: Chiude il blocco di script.
-
**`</body>`** e **`</html>`**: Chiudono il corpo e l'elemento HTML.
Considerazioni
Finali
Questo
codice crea una pagina web interattiva per tracciare le consegne a Lodi. Gli
utenti possono inserire un indirizzo e un oggetto, e vedere la mappa che mostra
il percorso dal punto di partenza all'indirizzo specificato, con un'animazione
del camion e un messaggio di conferma alla fine.
Pagina view_bookings.php
<?php
session_start();
// Controllo
se l'utente è loggato come amministratore
if
(!isset($_SESSION['admin'])) {
header("Location: index.php");
exit;
}
// Funzione
per leggere le prenotazioni
function
readBookings() {
return file('bookings.txt',
FILE_IGNORE_NEW_LINES);
}
// Funzione
per salvare le prenotazioni
function
saveBookings($bookings) {
file_put_contents('bookings.txt',
implode("\n", $bookings));
}
// Gestione
della cancellazione
if
(isset($_GET['delete'])) {
$bookings = readBookings();
unset($bookings[$_GET['delete']]);
saveBookings($bookings);
header("Location:
view_bookings.php");
exit;
}
// Gestione
della modifica
if
(isset($_POST['edit'])) {
$bookings = readBookings();
$index = $_POST['index'];
$bookings[$index] = $_POST['product'] . ':'
. $_POST['time'];
saveBookings($bookings);
header("Location:
view_bookings.php");
exit;
}
$bookings =
readBookings();
?>
<!DOCTYPE
html>
<html>
<head>
<title>Gestione
Prenotazioni</title>
</head>
<body>
<h2>Prenotazioni</h2>
<table border="1">
<tr>
<th>Prodotto</th>
<th>Ora</th>
<th>Azioni</th>
</tr>
<?php foreach ($bookings as $index
=> $booking): ?>
<?php list($product, $time) =
explode(':', $booking); ?>
<tr>
<td><?php echo
htmlspecialchars($product); ?></td>
<td><?php echo
htmlspecialchars($time); ?></td>
<td>
<form
method="post" style="display:inline;">
<input
type="hidden" name="index" value="<?php echo
$index; ?>">
<input
type="text" name="product" value="<?php echo
htmlspecialchars($product); ?>" required>
<input
type="datetime-local" name="time" value="<?php echo
htmlspecialchars($time); ?>" required>
<input type="submit"
name="edit" value="Modifica">
</form>
<a
href="?delete=<?php echo $index; ?>" onclick="return
confirm('Sei sicuro di voler cancellare questa
prenotazione?');">Cancella</a>
</td>
</tr>
<?php endforeach; ?>
</table>
<p><a
href="index.php">Torna al login</a></p>
<p><a
href="delivery.php">Gestione Consegna</a></p>
</body>
</html>
Spiegazione della pagina view_bookings.php
<?php
session_start();
-
**`session_start();`**: Avvia una nuova sessione o riprende una sessione
esistente, consentendo l'uso di variabili di sessione.
// Controllo
se l'utente è loggato come amministratore
if
(!isset($_SESSION['admin'])) {
header("Location: index.php");
exit;
}
- **`if
(!isset($_SESSION['admin'])) { ... }`**: Verifica se la variabile di sessione
`admin` è impostata. Se non lo è, significa che l'utente non è loggato come
amministratore.
-
**`header("Location: index.php");`**: Reindirizza l'utente alla
pagina di login (`index.php`).
-
**`exit;`**: Termina l'esecuzione dello script dopo il reindirizzamento.
// Funzione
per leggere le prenotazioni
function
readBookings() {
return file('bookings.txt',
FILE_IGNORE_NEW_LINES);
}
-
**`function readBookings() { ... }`**: Definisce una funzione per leggere le
prenotazioni dal file `bookings.txt`.
- **`return
file('bookings.txt', FILE_IGNORE_NEW_LINES);`**: Legge il contenuto del file e
restituisce un array, ignorando le nuove righe.
// Funzione
per salvare le prenotazioni
function
saveBookings($bookings) {
file_put_contents('bookings.txt',
implode("\n", $bookings));
}
-
**`function saveBookings($bookings) { ... }`**: Definisce una funzione per
salvare le prenotazioni nel file `bookings.txt`.
- **`file_put_contents('bookings.txt',
implode("\n", $bookings));`**: Converte l'array di prenotazioni in
una stringa (separata da nuove righe) e scrive nel file.
// Gestione
della cancellazione
if
(isset($_GET['delete'])) {
$bookings = readBookings();
unset($bookings[$_GET['delete']]);
saveBookings($bookings);
header("Location:
view_bookings.php");
exit;
}
- **`if
(isset($_GET['delete'])) { ... }`**: Controlla se è stata richiesta la
cancellazione di una prenotazione (tramite parametro GET).
-
**`$bookings = readBookings();`**: Legge le prenotazioni correnti.
-
**`unset($bookings[$_GET['delete']]);`**: Rimuove la prenotazione specificata
dall'array.
-
**`saveBookings($bookings);`**: Salva le prenotazioni aggiornate nel file.
-
**`header("Location: view_bookings.php");`**: Reindirizza alla pagina
delle prenotazioni.
-
**`exit;`**: Termina l'esecuzione dello script.
// Gestione
della modifica
if
(isset($_POST['edit'])) {
$bookings = readBookings();
$index = $_POST['index'];
$bookings[$index] = $_POST['product'] . ':'
. $_POST['time'];
saveBookings($bookings);
header("Location: view_bookings.php");
exit;
}
- **`if
(isset($_POST['edit'])) { ... }`**: Controlla se è stata richiesta la modifica
di una prenotazione.
-
**`$bookings = readBookings();`**: Legge le prenotazioni correnti.
- **`$index
= $_POST['index'];`**: Recupera l'indice della prenotazione da modificare.
-
**`$bookings[$index] = $_POST['product'] . ':' . $_POST['time'];`**: Aggiorna
la prenotazione con il nuovo prodotto e orario.
-
**`saveBookings($bookings);`**: Salva le modifiche nel file.
-
**`header("Location: view_bookings.php");`**: Reindirizza alla pagina
delle prenotazioni.
-
**`exit;`**: Termina l'esecuzione dello script.
$bookings =
readBookings();
-
**`$bookings = readBookings();`**: Legge tutte le prenotazioni e le memorizza
nella variabile `$bookings`.
<!DOCTYPE
html>
<html>
<head>
<title>Gestione
Prenotazioni</title>
</head>
<body>
<h2>Prenotazioni</h2>
-
**`<!DOCTYPE html>`**: Indica che il documento è in formato HTML5.
-
**`<html>`**: Inizia il documento HTML.
-
**`<head>`**: Contiene metadati e informazioni sul documento.
-
**`<title>Gestione Prenotazioni</title>`**: Imposta il titolo della
pagina.
-
**`<body>`**: Inizio del contenuto visibile della pagina.
-
**`<h2>Prenotazioni</h2>`**: Intestazione che descrive la sezione
delle prenotazioni.
<table border="1">
<tr>
<th>Prodotto</th>
<th>Ora</th>
<th>Azioni</th>
</tr>
-
**`<table border="1">`**: Crea una tabella con bordo.
-
**`<tr>`**: Inizio di una nuova riga nella tabella.
-
**`<th>`**: Definisce le intestazioni delle colonne della tabella.
<?php foreach ($bookings as $index
=> $booking): ?>
<?php list($product, $time) =
explode(':', $booking); ?>
<tr>
<td><?php echo
htmlspecialchars($product); ?></td>
<td><?php echo
htmlspecialchars($time); ?></td>
<td>
-
**`<?php foreach ($bookings as $index => $booking): ?>`**: Inizia un
ciclo per ogni prenotazione nell'array `$bookings`.
-
**`<?php list($product, $time) = explode(':', $booking); ?>`**: Divide la
stringa di prenotazione in prodotto e ora.
-
**`<tr>`**: Inizio di una nuova riga per la prenotazione.
-
**`<td><?php echo htmlspecialchars($product); ?></td>`**:
Mostra il nome del prodotto, assicurandosi che sia sicuro per l'output HTML.
-
**`<td><?php echo htmlspecialchars($time); ?></td>`**: Mostra
l'orario della prenotazione in modo sicuro.
<form
method="post" style="display:inline;">
<input
type="hidden" name="index" value="<?php echo
$index; ?>">
<input type="text"
name="product" value="<?php echo htmlspecialchars($product);
?>" required>
<input
type="datetime-local" name="time" value="<?php echo
htmlspecialchars($time); ?>" required>
<input
type="submit" name="edit" value="Modifica">
</form>
-
**`<td>`**: Inizio della colonna per le azioni.
-
**`<form method="post" style="display:inline;">`**:
Crea un modulo per la modifica della prenotazione, visualizzato in linea.
-
**`<input type="hidden" name="index"
value="<?php echo $index; ?>">`**: Campo nascosto che
memorizza l'indice della prenotazione.
-
**`<input type="text" name="product"
value="<?php echo htmlspecialchars($product); ?>"
required>`**: Campo di input per modificare il prodotto.
-
**`<input type="datetime-local" name="time"
value="<?php echo htmlspecialchars($time); ?>" required>`**:
Campo di input per modificare l'orario della prenotazione.
-
**`<input type="submit" name="edit"
value="Modifica">`**: Pulsante per inviare il modulo di modifica.
<a
href="?delete=<?php echo $index; ?>" onclick="return
confirm('Sei sicuro di voler cancellare questa
prenotazione?');">Cancella</a>
</td>
</tr>
<?php endforeach; ?>
</table>
- **`<a
href="?delete=<?php echo $index; ?>" ...
>Cancella</a>`**: Link per cancellare la prenotazione, passando
l'indice nella query string.
-
**`onclick="return confirm(...);`**: Mostra una finestra di conferma prima
di procedere con la cancellazione.
-
**`</td>`, `</tr>`**: Chiudono la cella e la riga della tabella.
-
**`<?php endforeach; ?>`**: Chiude il ciclo `foreach`.
-
**`</table>`**: Chiude la tabella.
<p><a
href="index.php">Torna al login</a></p>
<p><a
href="delivery.php">Gestione Consegna</a></p>
</body>
</html>
-
**`<p><a href="index.php">Torna al
login</a></p>`**: Link per tornare alla pagina di login.
-
**`<p><a href="delivery.php">Gestione
Consegna</a></p>`**: Link per accedere alla pagina di gestione
delle consegne.
-
**`</body>`** e **`</html>`**: Chiudono rispettivamente il corpo e
l'intero documento HTML.
Considerazioni
Finali
Questo
codice crea una pagina per la gestione delle prenotazioni, consentendo agli
amministratori di visualizzare, modificare e cancellare le prenotazioni
memorizzate in un file di testo. La pagina è protetta da accessi non
autorizzati grazie alla verifica della sessione.
Pagina logout.php
<?php
session_start();
session_destroy();
// Distrugge la sessione
header("Location:
index.php"); // Reindirizza alla pagina di login
exit;
?>
Spiegazione della pagina logout.php
Ecco una
spiegazione dettagliata, riga per riga, del codice PHP che gestisce la
disconnessione di un utente:
<?php
-
**`<?php`**: Inizia il blocco di codice PHP.
session_start();
-
**`session_start();`**: Avvia una nuova sessione o riprende una sessione
esistente. Questo è necessario per accedere e modificare le variabili di
sessione.
session_destroy();
// Distrugge la sessione
-
**`session_destroy();`**: Distrugge la sessione attuale e cancella tutte le
variabili di sessione associate. L'utente verrà disconnesso, e non sarà più in
grado di accedere a informazioni precedentemente memorizzate nella sessione.
header("Location:
index.php"); // Reindirizza alla pagina di login
-
**`header("Location: index.php");`**: Invia un'intestazione HTTP per
reindirizzare il browser alla pagina `index.php`, che di solito è la pagina di
login. Questo permette di guidare l'utente verso una schermata di accesso dopo
la disconnessione.
exit;
-
**`exit;`**: Termina l'esecuzione dello script PHP. È buona prassi usare `exit`
dopo un reindirizzamento per garantire che nessun ulteriore codice venga
eseguito.
Considerazioni
Finali
Questo
codice è tipicamente usato in un contesto di logout per disconnettere un utente
da una sessione attiva e reindirizzarlo alla pagina di login. È semplice e
diretto, assicurando che l'utente non possa più accedere a informazioni
riservate una volta disconnesso.
Queste ulteriori pagine permettono di salvare l'indirizzo di consegna, comprese le coordinate geografiche, in file di testo
Pagina delivery1.php
<!DOCTYPE
html>
<html
lang="it">
<head>
<meta charset="UTF-8">
<meta name="viewport"
content="width=device-width, initial-scale=1.0">
<title>Consegna a Lodi</title>
<link rel="stylesheet"
href="https://unpkg.com/leaflet/dist/leaflet.css" />
<link rel="stylesheet"
href="https://unpkg.com/leaflet-routing-machine/dist/leaflet-routing-machine.css"
/>
<style>
#map { height: 400px; width: 100%; }
#consegna { display: none; font-size:
20px; color: green; }
</style>
</head>
<body>
<h1>Tracciamento Consegna a Lodi</h1>
<form id="form">
<label
for="indirizzo">Indirizzo e Numero Civico:</label>
<input type="text"
id="indirizzo" placeholder="es: Viale Pavia 28, Lodi"
required>
<label
for="oggetto">Oggetto da Consegnare:</label>
<input type="text"
id="oggetto" placeholder="Descrivi l'oggetto" required>
<button
type="submit">Traccia Percorso</button>
</form>
<div id="map"></div>
<div id="consegna">✅
Consegna avvenuta!</div>
<script src="https://unpkg.com/leaflet/dist/leaflet.js"></script>
<script
src="https://unpkg.com/leaflet-routing-machine/dist/leaflet-routing-machine.js"></script>
<script>
const partenza = [45.3167, 9.5000]; //
Coordinate della paninoteca
const map =
L.map('map').setView(partenza, 13);
L.tileLayer('https://{s}.tile.openstreetmap.org/{z}/{x}/{y}.png', {
maxZoom: 19 }).addTo(map);
const routingControl =
L.Routing.control({ waypoints: [], routeWhileDragging: true }).addTo(map);
document.getElementById('form').onsubmit = async function(e) {
e.preventDefault();
const indirizzo =
document.getElementById('indirizzo').value;
const oggetto =
document.getElementById('oggetto').value;
// Geocodifica dell'indirizzo
const geoUrl =
`https://nominatim.openstreetmap.org/search?q=${encodeURIComponent(indirizzo)}&format=json&addressdetails=1`;
try {
const response = await
fetch(geoUrl);
const data = await response.json();
if (data.length === 0) {
alert('Indirizzo non
trovato. Assicurati di inserire un indirizzo valido.');
return;
}
const destinazione =
[data[0].lat, data[0].lon];
routingControl.setWaypoints([L.latLng(partenza[0], partenza[1]),
L.latLng(destinazione[0], destinazione[1])]);
const icon = L.icon({ iconUrl:
'https://img.icons8.com/ios-filled/50/000000/truck.png', iconSize: [32, 32] });
const truckMarker =
L.marker(partenza, { icon }).addTo(map);
// Salva indirizzo e coordinate nel file di testo
saveDelivery(indirizzo,
destinazione[0], destinazione[1]);
routingControl.on('routesfound', function(e) {
const route = e.routes[0];
let index = 0;
const moveTruck = () =>
{
if (index < route.coordinates.length) {
truckMarker.setLatLng(route.coordinates[index++]);
setTimeout(moveTruck, 100);
} else {
document.getElementById('consegna').innerHTML
= `✅ Consegna avvenuta a ${indirizzo} con oggetto: ${oggetto}!`;
document.getElementById('consegna').style.display = 'block';
}
};
moveTruck();
});
} catch (error) {
alert('Si è verificato un
errore durante la geocodifica. Riprova più tardi.');
}
};
// Funzione per salvare la consegna
function saveDelivery(address,
latitude, longitude) {
const deliveryUrl =
'save_delivery.php'; // PHP script che gestirà il salvataggio
fetch(deliveryUrl, {
method: 'POST',
headers: {
'Content-Type':
'application/x-www-form-urlencoded',
},
body:
`address=${encodeURIComponent(address)}&latitude=${latitude}&longitude=${longitude}`
});
}
</script>
</body>
</html>
Spiegazione del codice della pagina
delivery1.php
Ecco un'analisi
dettagliata del codice HTML e JavaScript fornito, riga per riga:
###
Struttura HTML di Base
<!DOCTYPE
html>
- Dichiara
che il documento è un file HTML5.
<html
lang="it">
- Apre
l'elemento `<html>` e specifica che la lingua del contenuto è l'italiano.
<head>
<meta charset="UTF-8">
- Imposta la
codifica dei caratteri su UTF-8, consentendo la visualizzazione di caratteri
speciali.
<meta name="viewport"
content="width=device-width, initial-scale=1.0">
- Configura
il viewport per rendere la pagina responsiva, ottimizzando la visualizzazione
su dispositivi mobili.
<title>Consegna a Lodi</title>
- Definisce
il titolo della pagina, visibile nella scheda del browser.
<link rel="stylesheet"
href="https://unpkg.com/leaflet/dist/leaflet.css" />
<link rel="stylesheet"
href="https://unpkg.com/leaflet-routing-machine/dist/leaflet-routing-machine.css"
/>
- Collega i
file CSS necessari per le librerie Leaflet e Leaflet Routing Machine,
utilizzate per la mappatura e la navigazione.
<style>
#map { height: 400px; width: 100%; }
#consegna { display: none; font-size:
20px; color: green; }
</style>
- Definisce
stili CSS interni. Imposta l'altezza e la larghezza della mappa e nasconde
inizialmente il messaggio di consegna.
### Corpo
della Pagina
<body>
<h1>Tracciamento Consegna a
Lodi</h1>
- Apre il
corpo della pagina e crea un'intestazione principale.
<form id="form">
- Apre un
elemento `<form>` con un identificatore per la gestione degli eventi.
<label
for="indirizzo">Indirizzo e Numero Civico:</label>
<input type="text"
id="indirizzo" placeholder="es: Viale Pavia 28, Lodi"
required>
- Crea
un'etichetta e un campo di input per l'indirizzo, con un segnaposto che mostra
un esempio.
<label
for="oggetto">Oggetto da Consegnare:</label>
<input type="text"
id="oggetto" placeholder="Descrivi l'oggetto" required>
- Crea
un'etichetta e un campo di input per descrivere l'oggetto da consegnare.
<button
type="submit">Traccia Percorso</button>
</form>
- Crea un
pulsante per inviare il modulo.
<div id="map"></div>
- Apre un
elemento `<div>` che conterrà la mappa generata da Leaflet.
<div id="consegna">✅
Consegna avvenuta!</div>
- Apre un
elemento `<div>` per mostrare un messaggio di conferma della consegna,
inizialmente nascosto.
### Script
JavaScript
<script
src="https://unpkg.com/leaflet/dist/leaflet.js"></script>
<script
src="https://unpkg.com/leaflet-routing-machine/dist/leaflet-routing-machine.js"></script>
- Collega le
librerie JavaScript necessarie per Leaflet e Leaflet Routing Machine.
<script>
const partenza = [45.3167, 9.5000]; //
Coordinate della paninoteca
- Definisce
una costante che contiene le coordinate della paninoteca come array.
const map =
L.map('map').setView(partenza, 13);
-
Inizializza la mappa Leaflet, impostando il punto di vista iniziale sulla
posizione di partenza con un livello di zoom di 13.
L.tileLayer('https://{s}.tile.openstreetmap.org/{z}/{x}/{y}.png', {
maxZoom: 19 }).addTo(map);
- Aggiunge
un livello di tile (mappa) utilizzando OpenStreetMap.
const routingControl =
L.Routing.control({ waypoints: [], routeWhileDragging: true }).addTo(map);
-
Inizializza il controllo di routing senza punti di passaggio iniziali e
consente di trascinare il percorso sulla mappa.
document.getElementById('form').onsubmit = async function(e) {
- Imposta un
gestore per l'evento di invio del modulo, utilizzando la sintassi `async` per
gestire le operazioni asincrone.
e.preventDefault();
- Impedisce
il comportamento predefinito del modulo, evitando il ricaricamento della
pagina.
const indirizzo =
document.getElementById('indirizzo').value;
const oggetto =
document.getElementById('oggetto').value;
- Estrae i
valori inseriti nei campi di input per l'indirizzo e l'oggetto.
const geoUrl =
`https://nominatim.openstreetmap.org/search?q=${encodeURIComponent(indirizzo)}&format=json&addressdetails=1`;
- Costruisce
l'URL per la richiesta di geocodifica, utilizzando l'API di Nominatim per
ottenere le coordinate dell'indirizzo.
try {
const response = await
fetch(geoUrl);
const data = await
response.json();
- Inizia un
blocco `try` per gestire eventuali errori, facendo una richiesta `fetch`
all'API di geocodifica e analizzando la risposta in formato JSON.
if (data.length === 0) {
alert('Indirizzo non
trovato. Assicurati di inserire un indirizzo valido.');
return;
}
- Controlla
se l'API ha restituito risultati. Se non ci sono risultati, mostra un messaggio
di avviso e interrompe l'esecuzione.
const destinazione =
[data[0].lat, data[0].lon];
- Estrae le
coordinate (latitudine e longitudine) dalla risposta dell'API.
routingControl.setWaypoints([L.latLng(partenza[0], partenza[1]),
L.latLng(destinazione[0], destinazione[1])]);
- Imposta i
punti di passaggio per il routing, includendo la partenza e la destinazione.
const icon = L.icon({ iconUrl:
'https://img.icons8.com/ios-filled/50/000000/truck.png', iconSize: [32, 32] });
const truckMarker =
L.marker(partenza, { icon }).addTo(map);
- Crea
un'icona personalizzata per il camion e aggiunge un marcatore sulla mappa alla
posizione di partenza.
saveDelivery(indirizzo,
destinazione[0], destinazione[1]);
- Chiama la
funzione `saveDelivery` per salvare l'indirizzo e le coordinate della consegna.
routingControl.on('routesfound',
function(e) {
- Aggiunge
un gestore per l'evento `routesfound`, che viene attivato quando viene trovata
una rotta.
const route = e.routes[0];
let index = 0;
- Estrae la
prima rotta trovata e inizializza un indice per il movimento del marcatore.
const moveTruck = () =>
{
if (index <
route.coordinates.length) {
truckMarker.setLatLng(route.coordinates[index++]);
setTimeout(moveTruck, 100);
} else {
- Definisce
una funzione `moveTruck` per animare il movimento del marcatore lungo il
percorso, aggiornando la sua posizione ogni 100 millisecondi.
document.getElementById('consegna').innerHTML = `✅ Consegna avvenuta a ${indirizzo}
con oggetto: ${oggetto}!`;
document.getElementById('consegna').style.display = 'block';
}
};
moveTruck();
- Una volta
raggiunta la destinazione, mostra un messaggio di conferma della consegna e
rende visibile il messaggio.
} catch (error) {
alert('Si è verificato un
errore durante la geocodifica. Riprova più tardi.');
}
- Gestisce
eventuali errori durante la geocodifica mostrando un messaggio di errore.
};
function saveDelivery(address,
latitude, longitude) {
const deliveryUrl =
'save_delivery.php'; // PHP script che gestirà il salvataggio
fetch(deliveryUrl, {
method: 'POST',
headers: {
'Content-Type':
'application/x-www-form-urlencoded',
},
body:
`address=${encodeURIComponent(address)}&latitude=${latitude}&longitude=${longitude}`
});
}
- Definisce
la funzione `saveDelivery`, che invia una richiesta POST al file
`save_delivery.php` con i dati dell'indirizzo e delle coordinate. Utilizza
l'API Fetch per inviare i dati in formato URL-encoded.
### Chiusura
dei Tag
</script>
</body>
</html>
- Chiude gli
script, il corpo della pagina e il documento HTML.
Riassunto
Il codice
crea una pagina web per tracciare le consegne, utilizzando Leaflet per la
mappatura e l'API di Nominatim per la geocodifica degli indirizzi. Gli utenti
possono inserire un indirizzo e un oggetto da consegnare, e il sistema calcola
e visualizza il percorso sulla mappa, mostrando anche un messaggio di conferma
alla fine della consegna.
Pagina save_delivery.php
<?php
if
($_SERVER['REQUEST_METHOD'] == 'POST') {
$address = $_POST['address'];
$latitude = $_POST['latitude'];
$longitude = $_POST['longitude'];
// Funzione per salvare le consegne
function saveDelivery($address, $latitude,
$longitude) {
$deliveryData =
"$address,$latitude,$longitude\n";
file_put_contents('deliveries.txt',
$deliveryData, FILE_APPEND);
}
saveDelivery($address, $latitude,
$longitude);
}
?>
Spiegazione della pagina save_delivery.php
Ecco
un'analisi dettagliata del codice PHP fornito, riga per riga:
<?php
- Inizia un
blocco di codice PHP.
if
($_SERVER['REQUEST_METHOD'] == 'POST') {
- Controlla
se il metodo della richiesta HTTP è POST. Questo significa che il codice
all'interno del blocco verrà eseguito solo quando i dati vengono inviati
tramite un modulo.
$address = $_POST['address'];
$latitude = $_POST['latitude'];
$longitude = $_POST['longitude'];
- Estrae i
valori delle variabili `address`, `latitude` e `longitude` dal superglobal
array `$_POST`, che contiene i dati inviati dal modulo. Queste variabili
rappresentano rispettivamente l'indirizzo, la latitudine e la longitudine della
consegna.
// Funzione per salvare le consegne
function saveDelivery($address, $latitude,
$longitude) {
- Definisce
una funzione chiamata `saveDelivery`, che accetta tre parametri: `address`,
`latitude` e `longitude`. Questa funzione è responsabile del salvataggio delle
informazioni di consegna.
$deliveryData =
"$address,$latitude,$longitude\n";
- Crea una
stringa `deliveryData` che contiene i dati di consegna formattati. Gli elementi
sono separati da virgole e termina con un carattere di nuova linea (`\n`), in
modo che ogni consegna venga salvata su una riga separata nel file.
file_put_contents('deliveries.txt',
$deliveryData, FILE_APPEND);
- Usa la
funzione `file_put_contents` per scrivere la stringa `deliveryData` nel file
`deliveries.txt`. L'opzione `FILE_APPEND` indica che i nuovi dati devono essere
aggiunti alla fine del file, invece di sovrascrivere il contenuto esistente.
}
- Chiude il
blocco della funzione `saveDelivery`.
saveDelivery($address, $latitude,
$longitude);
- Chiama la
funzione `saveDelivery`, passando i valori estratti precedentemente come
argomenti, per salvare i dati di consegna.
}
?>
- Chiude il
blocco `if` e il codice PHP.
Riassunto
Il codice
verifica se una richiesta è stata inviata tramite il metodo POST. Se sì, estrae
i dati dell'indirizzo e delle coordinate della consegna, e poi chiama una
funzione che salva queste informazioni in un file di testo chiamato
`deliveries.txt`. Ogni nuova consegna viene aggiunta alla fine del file.
link per scaricare l'intera procedura
Commenti
Posta un commento