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.

 Pagina index.php

<?php

session_start();

 function generateCaptcha() {

    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'];

     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>

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

Post popolari in questo blog

Esercizi in Excel e fogli di Google

Simulazioni di reti (con Cisco Packet Tracer)