Assigner sa BDD et la rendre scalable

Bienvenue sur ce cours que je vais tenter de vous présentez.


1: Présentation et attente


Ici nous allons voir ensemble un concept que j'ai imaginé pour vous, développeur Back-End & Data Scientist.


Tout d'abord sachez que cette façon de faire est redondante à tous les langages dit OOP, cependant il vous faudra notamment avoir vu les notions de Paradigme et maitriser certaines choses avancés dans l'univers de la programmation. ( Conceptualiser une Class, l'héritage de celle-ci, interagir de façon OOP, les Fonctions ... ).


Nous n'allons pas rentrer dans les détails de ce qu'est forcément les méthodes conventionnelles d'entreprise (cf: Model View Controller) mais de quelque chose, qui est utilisable à la fois dans ce type d'architecture comme dans vos Side Projects fait en procédural et qui nécessite une Base de Donnée.


Dans la suite du cour j'utiliserai le langage PHP, qui parlera peut être à beaucoup d'entrevous et qui vous facilitera la mise en place de celui-ci, j'ajouterai un exemple en NodeJS.


2: Le cours


Nous allons d'abord créer dans notre projet ces dossiers :

./backend
./backend/functions // <= Je ne vais pas forcément en parler, il est là pour apporter du contexte.
./backend/database // <= Notre élément principal de ce cours.


Ouvrez votre dossier database précédemment créé et vous allez y créer un fichier nommer : database.php.


Nous allons y construire notre class parent database et nous utiliserons notre extension PHP qui se nomme PDO. (PHP Data Objects)


Il est IMPORTANT d'être rigoureux et c'est pour cela qu'aucun algorithme de logique doit y être écris ou présent sous aucune forme, dans la simple et bonne raison que vous avez votre dossier function ( ./backend/function ) pour ça.



<?php
/** We create a new PDO database connection, set the PDO error mode to exception,
 * create a function to get the database connection,
 * create a query function to execute a query with args to the database and create a function to close the database connection.
 */
class Database {
    // We create a private variable for the database connection
    private $db;
    // We create a constructor for the database class
    public function __construct() {
        // We create a new PDO database connection
        $this->db = new PDO('mysql:host=localhost;dbname=database', 'username', 'password');
        // We set the PDO error mode to exception
        $this->db->setAttribute(PDO::ATTR_ERRMODE, PDO::ERRMODE_EXCEPTION);
    }
    // We create a function to get the database connection
    public function getConnection() {
        return $this->db;
    }
    // We create a query function to execute a query with args as PDO bindParam
    public function query($query, $args = []) {
        // We create a new PDO statement
        $stmt = $this->db->prepare($query);
        // We bind the args to the PDO statement
        foreach ($args as $key => $value) {
            $stmt->bindValue($key, $value);
        }
        // We execute the PDO statement
        $stmt->execute();
        // We return the PDO statement
        return $stmt;
    }
    // We create a function to close the database connection
    public function close() {
        $this->db = null;
    }
}


Puis nous allons créer un nouveau dossier dans notre dossier actuel, j'ai pour ma part pris l'habitude de l'appeler class, comme ceci:

./backend/database/class


Suivant notre rigueur, nous allons ici y créer les class correspondant à notre utilisation futur. Il est bien sur fortement recommander de créer des sous-dossiers pour être encore plus pertinents et structurer si votre projet deviens bien plus gros, nous ne voulons pas avoir des class qui traite de l'utilisateur et des class traitant du chat de la voisine.


Allons de ce pas créer nos fichiers

../class/users.php
../class/game.php


puis dans un second temps aller dans users.php et voici des elements d'utilisation:


<?php
class UsersDB extends Database {
    // we create a constructor for the UsersDB class
    public function __construct() {
        // we call the parent constructor
        parent::__construct();
    }


    // we create a function to add a new user, using parent::query()
    public function addUser($name, $email, $password) {
        $sql = "INSERT INTO users (name, email, password) VALUES (:name, :email, :password)";
        $arg = [':name' => $name, ':email' => $email, ':password' => $password];
        return parent::query($sql, $arg);
    }


    // we create a function to delete a user
    public function deleteUser($id) {
        $sql = "DELETE FROM users WHERE id = :id";
        $arg = [':id' => $id];
        return parent::query($sql, $arg);
    }


    // we create a function to update a user
    public function updateUser($id, $name, $email, $password) {
        $sql = "UPDATE users SET name = :name, email = :email, password = :password WHERE id = :id";
        $arg = [':id' => $id, ':name' => $name, ':email' => $email, ':password' => $password];
        return parent::query($sql, $arg);
    }


    // we create a function to get a user
    public function getUser($id) {
        $sql = "SELECT * FROM users WHERE id = :id";
        $arg = [':id' => $id];
        return parent::query($sql, $arg);
    }


    // we create a function to get a list of all users
    public function getAllUsers() {
        $sql = "SELECT * FROM users";
        $arg = [];
        return parent::query($sql, $arg);
    }
}


troisième temps

<?php
class GameDB extends Database {
    public function __construct() {
        parent::__construct();
    }


    public function getAllGame() {
        $sql = "SELECT * FROM game";
        $arg = [];
        return parent::query($sql, $arg);
    }


    public function addGame($name) {
        $sql = "INSERT INTO games (name) VALUES (:name)";
        $arg = [':name' => $name];
        return parent::query($sql, $arg);
    }


    public function updateGame($id, $name) {
        $sql = "UPDATE games SET name = :name WHERE id = :id";
        $arg = [':id' => $id, ':name' => $name];
        return parent::query($sql, $arg);
    }
}


Et voilà nous y sommes, il ne vous restera plus qu'à importer votre class enfant dans le fichier qui possède la fonction nécessitant la Query SQL correspondante.


3: Conclusion


Nous avons vu ensemble comment structurer convenablement nos éléments SQL en utilisant et étendant notre propre objet ::query pour rendre le reste de nos éléments plus pertinents.


Nous pouvons réutiliser nos éléments pour des utilisations différentes; output d'API, au sein d'un ou de plusieurs projets (...)


Nous pouvons aisément ajouter de nouvelles fonctions SQL.


Nous nous retrouverons jamais dans le cas ou nous avons une query sql en plein milieu de notre algorithme, mais directement sa fonction.


Il est bien sur pertinent pour les utilisateurs beaucoup plus avancés de définir des GETTER / SETTER.


Merci d'avoir lu ce cours c'était un plaisir pour moi de vous l'écrire, essayez et dites moi ce que vous en pensés ?


4: En NodeJS ça ressemble à quoi ?


database.mjs

import mysql from "mysql2";
export default class Database {
    constructor() {
        this.connection = mysql.createConnection({ host: "localhost", user: "root", password: "password", database: "database" });
    }


    async query(sql, args) {
        return await new Promise((resolve, reject) => {
            this.connection.query(sql, args, (err, rows) => {
                if (err) return reject(err);
                resolve(rows);
            });
        });
    }


    async close() {
        return await new Promise((resolve, reject) => {
            this.connection.end(err => {
                if (err) return reject(err);
                resolve();
            });
        });
    }
}


users.mjs

import Database from "../../database.mjs";
export default class Users extends Database {
    constructor() {
        super();
    }

    async GetAllUsers() {
        let sql = "SELECT * FROM users";
        let args = [];
        this.query(sql, args).then(rows => {
            return rows;
        }, err => {
            throw err;
        });
    }

    async DeleteUser(name) {
        let sql = "DELETE FROM users WHERE user_name = ?";
        let args = [name];
        this.query(sql, args).then(rows => {
            return rows;
        }, err => {
            throw err;
        });
    }

    async InsertUser(name, password, email) {
        let sql = "INSERT INTO users (user_name, password, email) VALUES (?, ?, ?)";
        let args = [name, password, email];
        this.query(sql, args).then(rows => {
            return rows;
        }, err => {
            throw err;
        });
    }
  }


*: J'ai marqué comme quoi je l'avais imaginer car je n'ai rien vu de pareil sur internet, ce n'est issu que de ma connaissances personnel.


Bonne journée à vous et happy coding !🌟

381 vues
11 juin 2022 à 21:46 (Édité)
Cette pub permet au site de vivre ...

1 commentaire

Tu veux participer ?
Alors connecte toi ou inscris toi et viens participer !

Bonsoir @AriusII:


Nous te remercions pour ta participation dans l'aventure du SiteDuDev 😁


A très vite 😎

Cette pub permet au site de vivre ...