Créa-blog

Ressources pour développeur web

Gestion d’une base de données en orientée objet avec PHP

Accueil PHP 8 Gestion d’une base de données en orientée objet avec PHP

Dans ce cours, nous allons découvrir comment intégrer une base de données dans notre application PHP orientée objet. Les bases de données sont un élément fondamental de nombreuses applications web, et en utilisant la POO, nous pouvons organiser notre code de manière efficace pour interagir avec celles-ci.

Différences entre table et base de données

Alors, imaginons que vous construisez une bibliothèque pour stocker tous vos livres. Vous pouvez penser à la base de données comme à la bibliothèque entière, tandis que chaque table serait comme une étagère dans cette bibliothèque.

Donc, dans votre bibliothèque (votre base de données), vous avez différentes étagères (tables) pour organiser vos livres. Par exemple, vous pourriez avoir une étagère pour les romans, une autre pour les livres d’histoire, une autre pour les livres de science-fiction, et ainsi de suite.

Chaque étagère (table) a son propre ensemble de livres (enregistrements de données). Sur l’étagère des romans, vous avez des livres de romans, sur l’étagère des livres d’histoire, vous avez des livres d’histoire, et ainsi de suite.

Une base de données est un conteneur global qui peut contenir plusieurs tables ainsi que d’autres objets de base de données, tandis qu’une table est une structure spécifique à l’intérieur de cette base de données qui organise les données de manière tabulaire.

MySQLi ou PDO

Le choix entre MySQLi et PDO (PHP Data Objects) dépend souvent des préférences personnelles, ainsi que des besoins spécifiques de votre projet. Les deux ont leurs avantages et leurs inconvénients :

MySQLi – MySQL Improved Extension

  • Orienté objet et procédural : MySQLi offre une interface orientée objet et une interface procédurale, ce qui permet aux développeurs de choisir la méthode qui leur convient le mieux.
  • Prise en charge des fonctionnalités spécifiques à MySQL : MySQLi offre un support natif pour des fonctionnalités spécifiques à MySQL, telles que les transactions et les procédures stockées.
  • Spécifique à MySQL : Comme son nom l’indique, MySQLi est spécifique à MySQL, ce qui signifie qu’il n’est pas aussi portable que PDO.
  • Syntaxe un peu plus verbeuse : La syntaxe de MySQLi peut sembler un peu plus verbeuse par rapport à PDO.

Voici un exemple de MySQLI en procédurale :

// Paramètres de connexion à la base de données
$servername = "localhost";
$username = "utilisateur";
$password = "motdepasse";
$database = "nom_base_de_donnees";

// Connexion à la base de données
$conn = mysqli_connect($servername, $username, $password, $database);

// Vérifier la connexion
if (!$conn) {
    die("Erreur de connexion à la base de données : " . mysqli_connect_error());
}

PDO – PHP Data Objects

  • Portabilité : PDO offre une abstraction de base de données qui permet de travailler avec différents types de bases de données, ce qui le rend plus portable.
  • Interface uniforme : PDO fournit une interface uniforme pour travailler avec différentes bases de données, ce qui facilite la transition entre les bases de données sans avoir à modifier beaucoup de code.
  • Prise en charge des transactions : Comme MySQLi, PDO prend en charge les transactions, ce qui est important pour les opérations critiques dans une base de données.
  • Moins de fonctionnalités spécifiques à MySQL : PDO ne prend pas en charge toutes les fonctionnalités spécifiques à MySQL, ce qui peut être un inconvénient si tu as besoin d’utiliser des fonctionnalités avancées de MySQL.
  • Moins de contrôle sur certaines fonctionnalités : Parfois, PDO peut offrir moins de contrôle sur certaines fonctionnalités spécifiques à une base de données par rapport à MySQLi.

Si vous souhaitez travailler uniquement avec MySQL et que vous avez besoin de fonctionnalités spécifiques à MySQL, MySQLi peut être un bon choix. Si vous envisagez de travailler avec plusieurs bases de données ou si vous voulez une solution plus portable, PDO peut être préférable. Dans les deux cas, assurez-vous de prendre en compte les besoins spécifiques de votre projet et choisissez la solution qui convient le mieux.

Configuration et connexion à une base de données avec MySQLi

Avant de commencer à travailler avec des bases de données dans notre application, nous devons configurer les informations de connexion. Pour ce faire, nous pouvons créer une classe dédiée à la gestion de la connexion à la base de données, comme suit :

class Database {
    private $host = "localhost";
    private $username = "utilisateur";
    private $password = "motdepasse";
    private $database = "nom_base_de_donnees";

    public function getConnection() {
        $conn = new mysqli($this->host, $this->username, $this->password, $this->database);
        if ($conn->connect_error) {
            die("Erreur de connexion à la base de données : " . $conn->connect_error);
        }
        return $conn;
    }
}

Création de classes pour interagir avec la base de données

Maintenant que notre connexion à la base de données est configurée, nous pouvons créer des classes dédiées à des tâches spécifiques, telles que l’exécution de requêtes SQL et la manipulation des données. Par exemple, supposons que nous ayons une classe User pour gérer les utilisateurs dans notre application. Voici comment cela pourrait être implémenté :

Récupérer des données depuis la base de données

require_once 'Database.php';

class User {
    private $conn;

    public function __construct() {
        $db = new Database();
        $this->conn = $db->getConnection();
    }

    public function getAllUsers() {
        $sql = "SELECT * FROM users";
        $result = $this->conn->query($sql);
        $users = [];
        if ($result->num_rows > 0) {
            while ($row = $result->fetch_assoc()) {
                $users[] = $row;
            }
        }
        return $users;
    }

    // Autres méthodes pour la manipulation des utilisateurs (ajout, suppression, mise à jour, etc.)
}

Maintenant que notre classe User est prête, nous pouvons l’utiliser dans notre application pour interagir avec la base de données. Par exemple, pour afficher tous les utilisateurs, nous pouvons faire ce qui suit :

require_once 'User.php';

$userObj = new User();
$users = $userObj->getAllUsers();

foreach ($users as $user) {
    echo "Nom d'utilisateur : " . $user['username'] . "
"; // Afficher d'autres informations d'utilisateur si nécessaire }

Modifier des entrées de la base de données

Nous allons modifier et étendre notre classe User pour inclure une méthode permettant de récupérer les informations d’un utilisateur et une autre méthode pour modifier ses informations dans la base de données :

require_once 'Database.php';

class User {
    private $conn;

    public function __construct() {
        $db = new Database();
        $this->conn = $db->getConnection();
    }

    // Méthode pour obtenir un utilisateur par son ID
    public function getUserById($userId) {
        $sql = "SELECT * FROM users WHERE id = ?";
        $stmt = $this->conn->prepare($sql);
        $stmt->bind_param("i", $userId);
        $stmt->execute();
        $result = $stmt->get_result();
        $user = $result->fetch_assoc();
        $stmt->close();
        return $user;
    }

    // Méthode pour mettre à jour les informations d'un utilisateur
    public function updateUser($userId, $newData) {
        $sql = "UPDATE users SET nom = ?, email = ? WHERE id = ?";
        $stmt = $this->conn->prepare($sql);
        $stmt->bind_param("ssi", $newData['nom'], $newData['email'], $userId);
        $result = $stmt->execute();
        $stmt->close();
        return $result;
    }
}

Dans cette nouvelle version de la classe User, nous avons ajouté une nouvelle méthode appelée getUserById($userId) :

  • La nouvelle méthode getUserById($userId) prend l’identifiant de l’utilisateur comme paramètre.
  • Dans cette méthode, nous préparons une requête SQL paramétrée pour sélectionner un utilisateur en fonction de son ID.
  • Nous lierons ensuite l’ID fourni en paramètre à la requête SQL pour éviter les attaques par injection SQL.
  • Nous exécutons la requête préparée, obtenons le résultat et renvoyons les données de l’utilisateur.
  • Enfin, nous fermons le statement pour libérer les ressources.

Nous avons également ajouté une nouvelle méthode appelée updateUser($userId, $newData) pour mettre à jour la base de données :

  • La méthode updateUser($userId, $newData) prend l’identifiant de l’utilisateur et les nouvelles données comme paramètres.
  • Nous préparons une requête SQL pour mettre à jour les informations de l’utilisateur dans la base de données.
  • Nous lierons les nouvelles données fournies en paramètres à la requête SQL pour éviter les attaques par injection SQL.
  • Nous exécutons la requête préparée pour effectuer la mise à jour des informations de l’utilisateur.
  • Enfin, nous retournons le résultat de l’opération de mise à jour.

Supprimer une entrée de la base de données

Voici comment vous pouvez étendre votre classe User pour inclure une méthode permettant de supprimer une entrée utilisateur de la base de données :

require_once 'Database.php';

class User {
    private $conn;

    public function __construct() {
        $db = new Database();
        $this->conn = $db->getConnection();
    }

    // Méthode pour obtenir un utilisateur par son ID
    public function getUserById($userId) {
        $sql = "SELECT * FROM users WHERE id = ?";
        $stmt = $this->conn->prepare($sql);
        $stmt->bind_param("i", $userId);
        $stmt->execute();
        $result = $stmt->get_result();
        $user = $result->fetch_assoc();
        $stmt->close();
        return $user;
    }

    // Méthode pour mettre à jour les informations d'un utilisateur
    public function updateUser($userId, $newData) {
        $sql = "UPDATE users SET nom = ?, email = ? WHERE id = ?";
        $stmt = $this->conn->prepare($sql);
        $stmt->bind_param("ssi", $newData['nom'], $newData['email'], $userId);
        $result = $stmt->execute();
        $stmt->close();
        return $result;
    }

    // Méthode pour supprimer un utilisateur par son ID
    public function deleteUser($userId) {
        $sql = "DELETE FROM users WHERE id = ?";
        $stmt = $this->conn->prepare($sql);
        $stmt->bind_param("i", $userId);
        $result = $stmt->execute();
        $stmt->close();
        return $result;
    }
}

Dans cette nouvelle version de la classe User :

  • Nous avons ajouté une nouvelle méthode appelée deleteUser($userId) qui prend l’identifiant de l’utilisateur à supprimer comme paramètre.
  • Nous préparons une requête SQL pour supprimer l’utilisateur de la base de données en fonction de son ID.
  • Nous lierons l’ID de l’utilisateur fourni en paramètre à la requête SQL pour éviter les attaques par injection SQL.
  • Nous exécutons la requête préparée pour supprimer l’utilisateur de la base de données.
  • Enfin, nous retournons le résultat de l’opération de suppression.

Cette méthode permet de supprimer une entrée utilisateur de la base de données, ce qui peut être utile lorsque vous avez besoin de retirer un utilisateur de votre système.

Lier pour éviter les attaques par injections SQL

Lorsqu’il est écrit nous lierons l’ID dans le contexte de la préparation d’une requête SQL, cela fait référence à l’utilisation des paramètres de requête pour sécuriser la requête contre les attaques par injection SQL.

Dans le langage des bases de données et des requêtes préparées, lier signifie associer une valeur à un paramètre de requête. Les paramètres de requête sont des espaces réservés dans une requête SQL qui seront remplacés par les valeurs fournies lors de l’exécution de la requête.

Dans notre exemple, lorsque nous utilisons des paramètres de requête, nous indiquons à MySQL que les données fournies pour les paramètres ne sont pas du code SQL, mais plutôt des valeurs à traiter de manière sécurisée.

Par exemple, lorsque il écrit :

$sql = "DELETE FROM users WHERE id = ?";
$stmt = $this->conn->prepare($sql);
$stmt->bind_param("i", $userId);

Nous définissons un paramètre de requête ? dans la requête SQL pour l’ID de l’utilisateur. Ensuite, avec bind_param, nous lions la variable $userId au paramètre de requête. La lettre i dans bind_param indique que $userId est un entier (int), ce qui permet à MySQL de le traiter correctement.

Cette approche rend la requête SQL sécurisée contre les attaques par injection SQL car même si la valeur de $userId contient des caractères spéciaux, ils seront interprétés comme des données et non pas comme du code SQL à exécuter.

Pour en savoir plus sur la sécurisation des bases de données, consultez notre chapitre sur sur les injections SQL.

En utilisant la POO avec PHP, nous pouvons simplifier la gestion des bases de données dans nos applications. En organisant notre code en classes et en méthodes, nous rendons notre code plus lisible, modulaire et facile à maintenir. Avec les concepts de la POO et l’accès aux bases de données, les possibilités pour développer des applications web puissantes et évolutives sont infinies.

Pour tout savoir sur les injections SQL, consulter le chapitre : Protéger ses données des injections SQL.