Système de gestion du consentement des cookies en PHP avec catégories, granularité et journal des modifications

Système PHP complet pour gérer le consentement des cookies avec catégories, granularité, journal des modifications et conformité RGPD.

Brève Introduction

Système de gestion du consentement des cookies en PHP avec catégories, granularité et journal des modifications (php)
DESCRIPTION :
Implémentation robuste en PHP d'un système de gestion du consentement des cookies, avec prise en charge de plusieurs catégories, granularité d'acceptation, sauvegarde en base de données et journalisation des modifications pour audit.

NOTES SUPPLÉMENTAIRES :
Le système est conçu pour être facilement intégré dans des sites web PHP existants. La granularité permet à l'utilisateur d'accepter ou de refuser des catégories individuelles de cookies (ex. marketing, analytiques, fonctionnels). Le journal des modifications permet de tracer chaque variation du consentement pour des raisons de conformité RGPD.

EXPLICATIONS :
- La table 'consensi_cookie' stocke pour chaque utilisateur l'acceptation ou non de chaque catégorie de cookies.
- La table 'log_consensi' enregistre chaque modification effectuée, avec horodatage et adresse IP pour audit.
- Le fichier config.php définit les catégories de cookies et les paramètres de connexion à la base de données pour faciliter la maintenance.
- Le frontend affiche une modale avec des cases à cocher pour chaque catégorie, sauvegardant les choix via AJAX vers le backend PHP.
- Le backend valide les données reçues, met à jour la base de données et enregistre le journal de manière atomique avec des transactions PDO.
- Les commentaires dans le code sont en italien pour faciliter la compréhension et la maintenance future.

Code d'Exemple : php

<?php
// config.php - configuration base de données et catégories de cookies
return [
    'db' => [
        'host' => 'localhost',
        'dbname' => 'cookie_consent',
        'user' => 'dbuser',
        'pass' => 'dbpassword',
        'charset' => 'utf8mb4'
    ],
    'cookie_categories' => [
        'necessari' => 'Cookies nécessaires au fonctionnement du site',
        'funzionali' => 'Cookies améliorant l\'expérience utilisateur',
        'analitici' => 'Cookies pour analyses statistiques anonymes',
        'marketing' => 'Cookies pour campagnes publicitaires personnalisées'
    ]
];

// db.php - classe pour gestion de la connexion PDO
class Database {
    private static ?\PDO $pdo = null;

    public static function getConnection(): \PDO {
        if (self::$pdo === null) {
            $config = require __DIR__ . '/config.php';
            $db = $config['db'];
            $dsn = "mysql:host={$db['host']};dbname={$db['dbname']};charset={$db['charset']}";
            $options = [
                \PDO::ATTR_ERRMODE => \PDO::ERRMODE_EXCEPTION,
                \PDO::ATTR_DEFAULT_FETCH_MODE => \PDO::FETCH_ASSOC,
                \PDO::ATTR_EMULATE_PREPARES => false,
            ];
            try {
                self::$pdo = new \PDO($dsn, $db['user'], $db['pass'], $options);
            } catch (\PDOException $e) {
                // Gestion erreur de connexion
                die('Erreur de connexion DB : ' . $e->getMessage());
            }
        }
        return self::$pdo;
    }
}

// consent_manager.php - classe pour gestion des consentements et journal
class ConsentManager {
    private \PDO $pdo;
    private array $categories;

    public function __construct() {
        $this->pdo = Database::getConnection();
        $config = require __DIR__ . '/config.php';
        $this->categories = $config['cookie_categories'];
        session_start(); // pour gestion utilisateur
    }

    /**
     * Récupère les consentements actuels pour l'utilisateur
     * @param int|null $userId
     * @return array
     */
    public function getUserConsents(?int $userId): array {
        if ($userId === null) {
            return [];
        }
        $stmt = $this->pdo->prepare('SELECT categoria, accettato FROM consensi_cookie WHERE user_id = ?');
        $stmt->execute([$userId]);
        $result = $stmt->fetchAll();
        $consents = [];
        foreach ($result as $row) {
            $consents[$row['categoria']] = (bool)$row['accettato'];
        }
        return $consents;
    }

    /**
     * Sauvegarde les consentements fournis par l'utilisateur et enregistre le journal
     * @param int $userId
     * @param array $consents tableau associatif catégorie => bool
     * @return bool
     */
    public function saveUserConsents(int $userId, array $consents): bool {
        // Validation des catégories
        foreach ($consents as $cat => $val) {
            if (!array_key_exists($cat, $this->categories)) {
                throw new InvalidArgumentException("Catégorie de cookie non valide : $cat");
            }
        }

        try {
            $this->pdo->beginTransaction();

            // Récupère les consentements actuels pour comparaison
            $oldConsents = $this->getUserConsents($userId);

            // Insertion ou mise à jour des consentements
            $stmtInsert = $this->pdo->prepare(
                'INSERT INTO consensi_cookie (user_id, categoria, accettato) VALUES (?, ?, ?)'
                . ' ON DUPLICATE KEY UPDATE accettato = VALUES(accettato)'
            );

            foreach ($this->categories as $cat => $_) {
                $accepted = isset($consents[$cat]) ? (bool)$consents[$cat] : false;
                $stmtInsert->execute([$userId, $cat, $accepted ? 1 : 0]);

                // Si le consentement a changé, enregistrer le log
                $oldVal = $oldConsents[$cat] ?? null;
                if ($oldVal !== $accepted) {
                    $this->logChange($userId, $cat, $oldVal, $accepted);
                }
            }

            $this->pdo->commit();
            return true;
        } catch (\Exception $e) {
            $this->pdo->rollBack();
            error_log('Erreur sauvegarde consentements : ' . $e->getMessage());
            return false;
        }
    }

    /**
     * Enregistre une modification de consentement dans le journal
     * @param int $userId
     * @param string $categoria
     * @param bool|null $oldValue
     * @param bool $newValue
     * @return void
     */
    private function logChange(int $userId, string $categoria, ?bool $oldValue, bool $newValue): void {
        $stmt = $this->pdo->prepare('INSERT INTO log_consensi (user_id, categoria, vecchio_valore, nuovo_valore, ip, timestamp) VALUES (?, ?, ?, ?, ?, NOW())');
        $ip = $_SERVER['REMOTE_ADDR'] ?? 'unknown';
        $stmt->execute([
            $userId,
            $categoria,
            $oldValue === null ? null : ($oldValue ? 1 : 0),
            $newValue ? 1 : 0,
            $ip
        ]);
    }
}

// Exemple d'utilisation dans un endpoint API (save_consent.php)
if ($_SERVER['REQUEST_METHOD'] === 'POST') {
    header('Content-Type: application/json');

    // Simulation d'utilisateur authentifié avec ID en session
    session_start();
    $userId = $_SESSION['user_id'] ?? null;

    if ($userId === null) {
        http_response_code(401);
        echo json_encode(['error' => 'Utilisateur non authentifié']);
        exit;
    }

    $input = json_decode(file_get_contents('php://input'), true);
    if (!is_array($input)) {
        http_response_code(400);
        echo json_encode(['error' => 'Entrée non valide']);
        exit;
    }

    $consentManager = new ConsentManager();

    try {
        $success = $consentManager->saveUserConsents($userId, $input);
        if ($success) {
            echo json_encode(['success' => true]);
        } else {
            http_response_code(500);
            echo json_encode(['error' => 'Erreur sauvegarde consentements']);
        }
    } catch (InvalidArgumentException $e) {
        http_response_code(400);
        echo json_encode(['error' => $e->getMessage()]);
    }
}

// Schéma des tables SQL (à exécuter une fois)
/*
CREATE TABLE utenti (
    id INT AUTO_INCREMENT PRIMARY KEY,
    username VARCHAR(100) NOT NULL UNIQUE,
    password_hash VARCHAR(255) NOT NULL
) ENGINE=InnoDB DEFAULT CHARSET=utf8mb4;

CREATE TABLE consensi_cookie (
    user_id INT NOT NULL,
    categoria VARCHAR(50) NOT NULL,
    accettato TINYINT(1) NOT NULL DEFAULT 0,
    PRIMARY KEY (user_id, categoria),
    FOREIGN KEY (user_id) REFERENCES utenti(id) ON DELETE CASCADE
) ENGINE=InnoDB DEFAULT CHARSET=utf8mb4;

CREATE TABLE log_consensi (
    id INT AUTO_INCREMENT PRIMARY KEY,
    user_id INT NOT NULL,
    categoria VARCHAR(50) NOT NULL,
    vecchio_valore TINYINT(1) NULL,
    nuovo_valore TINYINT(1) NOT NULL,
    ip VARCHAR(45) NOT NULL,
    timestamp DATETIME NOT NULL,
    FOREIGN KEY (user_id) REFERENCES utenti(id) ON DELETE CASCADE
) ENGINE=InnoDB DEFAULT CHARSET=utf8mb4;
*/

?>
×
×
×
Veux-tu régénérer la réponse ?
×
Exporter le chat
Choisissez le format d'export
⏳ Generazione PDF in corso…
Allegati
×
⚠️ Vous êtes sur le point de fermer le chat et de passer au générateur d’images. Si vous n’êtes pas connecté, vous perdrez notre conversation. Confirmez-vous ?
👁 Tu consultes une discussion partagée en mode temporaire. Elle ne sera pas enregistrée.
💬
×
Prompts enregistrés
×
Note privée
×
Étiquette
×
Rechercher dans toutes les discussions
×
Vos insights
Analyse en cours…
×
Préférences IA
Nom de l'assistant 30
Longueur des réponses
Modèle IA
Réponses structurées
Inclure des exemples
Utiliser des emojis
Guide-moi, ne résous pas Des indices et des questions plutôt que la réponse toute faite
Plus de réglages →
×
Partager cette discussion
Toute personne ouvrant ce lien pourra consulter la discussion ou l'ajouter à son profil comme discussion personnelle.
⚠️ Attention : les pièces jointes de la discussion seront également partagées. Qui l'ajoutera recevra une copie des fichiers dans son dossier.
Discussion partagée
Quelqu'un a partagé une discussion avec toi. Veux-tu seulement la consulter ou l'ajouter à tes discussions ?
⚠️ Attention : les pièces jointes de la discussion seront également partagées. Qui l'ajoutera recevra une copie des fichiers dans son dossier.
×

📌 Messages enregistrés

Chargement...

×

Historique des discussions

programmes-exemples · HISTORIQUE DU CHAT

Chargement...

Préférences IA

×
  • 🟢 BasiqueRéponses rapides et essentielles pour étudier
  • 🔵 MoyenQualité supérieure pour étude et programmation
  • 🟣 AvancéRaisonnement complexe et analyses détaillées
Expliquer les étapes

Exemple Complet

<?php
// Exemple complet minimal pour tester le système de gestion du consentement des cookies

// Inclure le code original tel quel
// config.php
file_put_contents(__DIR__ . '/config.php', <<<'CONFIG'
<?php
return [
    'db' => [
        'host' => 'localhost',
        'dbname' => 'cookie_consent',
        'user' => 'dbuser',
        'pass' => 'dbpassword',
        'charset' => 'utf8mb4'
    ],
    'cookie_categories' => [
        'necessari' => 'Cookies nécessaires au fonctionnement du site',
        'funzionali' => 'Cookies améliorant l\'expérience utilisateur',
        'analitici' => 'Cookies pour analyses statistiques anonymes',
        'marketing' => 'Cookies pour campagnes publicitaires personnalisées'
    ]
];
CONFIG
);

// db.php
file_put_contents(__DIR__ . '/db.php', <<<'DB'
<?php
class Database {
    private static ?\PDO $pdo = null;

    public static function getConnection(): \PDO {
        if (self::$pdo === null) {
            $config = require __DIR__ . '/config.php';
            $db = $config['db'];
            $dsn = "mysql:host={$db['host']};dbname={$db['dbname']};charset={$db['charset']}";
            $options = [
                \PDO::ATTR_ERRMODE => \PDO::ERRMODE_EXCEPTION,
                \PDO::ATTR_DEFAULT_FETCH_MODE => \PDO::FETCH_ASSOC,
                \PDO::ATTR_EMULATE_PREPARES => false,
            ];
            try {
                self::$pdo = new \PDO($dsn, $db['user'], $db['pass'], $options);
            } catch (\PDOException $e) {
                die('Erreur de connexion DB : ' . $e->getMessage());
            }
        }
        return self::$pdo;
    }
}
DB
);

// consent_manager.php
file_put_contents(__DIR__ . '/consent_manager.php', <<<'CONSENT'
<?php
class ConsentManager {
    private \PDO $pdo;
    private array $categories;

    public function __construct() {
        $this->pdo = Database::getConnection();
        $config = require __DIR__ . '/config.php';
        $this->categories = $config['cookie_categories'];
        if(session_status() !== PHP_SESSION_ACTIVE) {
            session_start();
        }
    }

    public function getUserConsents(?int $userId): array {
        if ($userId === null) {
            return [];
        }
        $stmt = $this->pdo->prepare('SELECT categoria, accettato FROM consensi_cookie WHERE user_id = ?');
        $stmt->execute([$userId]);
        $result = $stmt->fetchAll();
        $consents = [];
        foreach ($result as $row) {
            $consents[$row['categoria']] = (bool)$row['accettato'];
        }
        return $consents;
    }

    public function saveUserConsents(int $userId, array $consents): bool {
        foreach ($consents as $cat => $val) {
            if (!array_key_exists($cat, $this->categories)) {
                throw new InvalidArgumentException("Catégorie de cookie non valide : $cat");
            }
        }

        try {
            $this->pdo->beginTransaction();

            $oldConsents = $this->getUserConsents($userId);

            $stmtInsert = $this->pdo->prepare(
                'INSERT INTO consensi_cookie (user_id, categoria, accettato) VALUES (?, ?, ?)'
                . ' ON DUPLICATE KEY UPDATE accettato = VALUES(accettato)'
            );

            foreach ($this->categories as $cat => $_) {
                $accepted = isset($consents[$cat]) ? (bool)$consents[$cat] : false;
                $stmtInsert->execute([$userId, $cat, $accepted ? 1 : 0]);

                $oldVal = $oldConsents[$cat] ?? null;
                if ($oldVal !== $accepted) {
                    $this->logChange($userId, $cat, $oldVal, $accepted);
                }
            }

            $this->pdo->commit();
            return true;
        } catch (\Exception $e) {
            $this->pdo->rollBack();
            error_log('Erreur sauvegarde consentements : ' . $e->getMessage());
            return false;
        }
    }

    private function logChange(int $userId, string $categoria, ?bool $oldValue, bool $newValue): void {
        $stmt = $this->pdo->prepare('INSERT INTO log_consensi (user_id, categoria, vecchio_valore, nuovo_valore, ip, timestamp) VALUES (?, ?, ?, ?, ?, NOW())');
        $ip = $_SERVER['REMOTE_ADDR'] ?? 'unknown';
        $stmt->execute([
            $userId,
            $categoria,
            $oldValue === null ? null : ($oldValue ? 1 : 0),
            $newValue ? 1 : 0,
            $ip
        ]);
    }
}
CONSENT
);

// Création des tables SQL pour test (exécuter une seule fois)
// Ici on suppose que la base de données 'cookie_consent' existe et que l'utilisateur a les droits
try {
    $pdo = Database::getConnection();
    $pdo->exec("CREATE TABLE IF NOT EXISTS utenti (
        id INT AUTO_INCREMENT PRIMARY KEY,
        username VARCHAR(100) NOT NULL UNIQUE,
        password_hash VARCHAR(255) NOT NULL
    ) ENGINE=InnoDB DEFAULT CHARSET=utf8mb4;");

    $pdo->exec("CREATE TABLE IF NOT EXISTS consensi_cookie (
        user_id INT NOT NULL,
        categoria VARCHAR(50) NOT NULL,
        accettato TINYINT(1) NOT NULL DEFAULT 0,
        PRIMARY KEY (user_id, categoria),
        FOREIGN KEY (user_id) REFERENCES utenti(id) ON DELETE CASCADE
    ) ENGINE=InnoDB DEFAULT CHARSET=utf8mb4;");

    $pdo->exec("CREATE TABLE IF NOT EXISTS log_consensi (
        id INT AUTO_INCREMENT PRIMARY KEY,
        user_id INT NOT NULL,
        categoria VARCHAR(50) NOT NULL,
        vecchio_valore TINYINT(1) NULL,
        nuovo_valore TINYINT(1) NOT NULL,
        ip VARCHAR(45) NOT NULL,
        timestamp DATETIME NOT NULL,
        FOREIGN KEY (user_id) REFERENCES utenti(id) ON DELETE CASCADE
    ) ENGINE=InnoDB DEFAULT CHARSET=utf8mb4;");

    // Insérer un utilisateur de test si pas existant
    $stmt = $pdo->prepare('SELECT id FROM utenti WHERE username = ?');
    $stmt->execute(['testuser']);
    $user = $stmt->fetch();
    if (!$user) {
        $passwordHash = password_hash('testpass', PASSWORD_DEFAULT);
        $stmtInsert = $pdo->prepare('INSERT INTO utenti (username, password_hash) VALUES (?, ?)');
        $stmtInsert->execute(['testuser', $passwordHash]);
        $userId = $pdo->lastInsertId();
    } else {
        $userId = $user['id'];
    }
} catch (\PDOException $e) {
    die('Erreur lors de la création des tables ou insertion utilisateur : ' . $e->getMessage());
}

// Simulation d'une session utilisateur
if(session_status() !== PHP_SESSION_ACTIVE) {
    session_start();
}
$_SESSION['user_id'] = (int)$userId;

// Test de sauvegarde des consentements
$consentManager = new ConsentManager();

// Exemple de consentements à sauvegarder
$consents = [
    'necessari' => true,
    'funzionali' => false,
    'analitici' => true,
    'marketing' => false
];

$success = $consentManager->saveUserConsents($userId, $consents);

if ($success) {
    echo "Consentements sauvegardés avec succès.\n";
    $savedConsents = $consentManager->getUserConsents($userId);
    echo "Consentements actuels pour l'utilisateur :\n";
    print_r($savedConsents);
} else {
    echo "Erreur lors de la sauvegarde des consentements.\n";
}

?>

Qu'est-ce qu'il faut ?

Backend PHP 8+ avec PDO pour un accès sécurisé à la base de données MySQL/MariaDB

Base de données MySQL avec tables : utilisateurs, consensi_cookie, log_consensi

Frontend HTML5 + JavaScript pour interface utilisateur de sélection des catégories de cookies

Fichier de configuration PHP pour définition des catégories de cookies et paramètres DB

Système de journalisation personnalisé pour tracer les modifications des consentements

Dépendances logicielles : extension PDO activée, session PHP active

Configuration base de données : hôte, nom db, utilisateur, mot de passe dans le fichier config.php

Aucun matériel Arduino requis pour ce projet

Sujets Similaires

Premier script PHP : afficher un message à l’écran
Script PHP simple pour afficher un message de bienvenue à l’écran, idéal pour débutants souhaitant un résultat visible rapidement en environnement web.
Page PHP affichant la date et l’heure actuelles
Script PHP simple affichant la date et l’heure actuelles au format jour mois année heure minute seconde avec configuration du fuseau horaire.
Calculatrice très simple avec deux nombres en PHP
Script PHP simple pour additionner deux nombres via un formulaire HTML avec validation et affichage sécurisé du résultat sur la même page.
Formulaire PHP qui salue l’utilisateur par son nom
Formulaire PHP simple qui accueille l utilisateur par son nom avec méthode POST pour une saisie sécurisée et un message personnalisé facile à intégrer.
Page PHP qui compte combien de fois elle a été visitée
Script PHP simple qui compte et affiche le nombre de visites d’une page web en utilisant un fichier texte pour stocker le compteur de manière persistante.
Liste statique de produits affichée avec PHP
Exemple simple en PHP affichant une liste statique de produits avec nom, description et prix, idéal pour apprendre la gestion des tableaux et l’affichage HTML.
Page PHP qui génère un tableau HTML à partir d’un tableau
Page PHP simple qui génère dynamiquement un tableau HTML à partir d’un tableau multidimensionnel sans dépendances externes, idéale pour débutants en PHP.
Mini carnet d’adresses en PHP avec un tableau de contacts
Mini carnet d’adresses en PHP utilisant un tableau associatif pour gérer, afficher et rechercher des contacts sans base de données ni configuration externe.