Logs
Consultez les logs.
OK
Liste des données
Consultez la liste des données.
OK
Loading...
Formulaire
Saisissez vos données.
Enregistrer
Annuler

Apprendre PHP

Vues
488

Bienvenue dans ce tutoriel consacré à l'apprentissage des technologies liées au développement d'applications Web en PHP sous l'environnement Windows.
Produit par Gérard KESSE.



Introduction


PHP est un langage de script orienté objet prenant en charge la création de de pages WEB dynamiques.


### Travailler avec PHP


PHP est un langage de script orienté objet prenant en charge la création de de pages WEB dynamiques.


Créer un serveur web PHP de gestion des utilisateurs avec WampServer sous Windows


PHP est un langage de script orienté objet prenant en charge la création de système de gestion des utilisateurs. WampServer est un ensemble d'outils (Windows Apache MySQL PHP) prenant en charge les projets web PHP sous Windows. Apache est un serveur HTTP supporté par les scripts PHP. MySQL est un système de gestion de bases de données relationnelles client/serveur (à distance sur un serveur de données) pris en charge par le développement PHP. SQLite est un système de gestion de bases de données relationnelles embarqué (en locale dans un fichier) géré par le développement PHP. SQL est un langage de requête structurée (Structured Query Language) utilisé pour gérer la communication avec les systèmes de gestion de base de données relationnelles. Dans ce tutoriel, nous utiliserons le module Apache pour mettre en place un serveur WEB de gestion des utilisateurs permettant de créer un compte d'utilisateur à partir d'un nom d'utilisateur et d'un mot de passe. Un identifiant UUID sera généré pour chaque utilisateur inscrit. L'identifiant UUID sera mis en session pour chaque utilisateur connecté et ne devra pas être renvoyé au client. Les échanges de données avec le serveur seront attribués au compte de l'utilisateur correspond à l'identifiant UUID mis en session. La déconnexion d'un utilisateur correspondra à la suppression de l'identifiant UUID mis en session. Nous utiliserons le module SQLite pour sauvegarder et gérer les données de l'application à travers des requêtes SQL. Nous mettrons en place un système de mise à jour MAJ automatisé des schémas de la base de données SQL. Dans un soucis d'agilité face aux évolutions de l'application, nous utiliserons les principes de développement SOLID et OBJET VALIDE.


Gestion de l'interface frontend PHP



Gestion du chargement automatique de classes PHP

// php\autoload.php (Charger automatiquement les classes PHP)
...
<?php

declare(strict_types=1);

session_start();

function onAutoload($_classname)
{
    $classname = $_SERVER["DOCUMENT_ROOT"] . DIRECTORY_SEPARATOR . $_classname . ".php";
    //echo sprintf("[Info]:autoload...|classname=%s\n", $classname);
    require $classname;
}

spl_autoload_register('onAutoload');
...

Gestion du point d'entrée de la page WEB


// index.php (Gérer le point d'entrée de la page WEB)
...
<?php

declare(strict_types=1);
require $_SERVER["DOCUMENT_ROOT"] . DIRECTORY_SEPARATOR . "/php/autoload.php";
require $_SERVER["DOCUMENT_ROOT"] . DIRECTORY_SEPARATOR . "/libs/logger/logger.php";
require $_SERVER["DOCUMENT_ROOT"] . DIRECTORY_SEPARATOR . "/libs/uuid/uuid.php";

$oHtml = new php\ui\cHtml();
$oPageHTML = "";
$oHtml->run($oPageHTML);
echo $oPageHTML;
...

Gestion de la structure de base d'une page HTML


// php\ui\cHtml.php (Gérer la structure de base d'une page HTML)
...
<?php

declare(strict_types=1);

namespace php\ui;

class sHtml
{
    public $title = "";
    public $encoding = "";
    public $lang = "";
    public $logo = "";
    public $mimeType = "";
}

class cHtml
{
    public function __construct() {}

    public function run(string &$_html): void
    {
        $oHtml = new sHtml();
        $this->initHtml($oHtml);

        $oBodyHTML = "";
        $oBody = new cBody();
        $oBody->run($oBodyHTML);

        $_html .= sprintf("<!DOCTYPE html>\n");
        $_html .= sprintf("<html lang='%s'>\n", $oHtml->lang);
        $_html .= sprintf("<head>\n");
        $_html .= sprintf("<title>%s</title>\n", $oHtml->title);
        $_html .= sprintf("<meta charset='%s'/>\n", $oHtml->encoding);
        $_html .= sprintf("<link rel='shortcut icon' type='%s' href='%s'/>\n", $oHtml->mimeType, $oHtml->logo);
        $_html .= sprintf("<meta name='viewport' content='width=device-width, maximum-scale=1.0, minimum-scale=1.0, initial-scale=1.0, user-scalable=no'/>\n");
        $_html .= sprintf("<link rel='stylesheet' href='/libs/font-awesome/css/font-awesome.min.css'/>");
        $_html .= sprintf("<link rel='stylesheet' href='/css/styles.css'/>\n");
        $_html .= sprintf("</head>\n");
        $_html .= sprintf("<body>\n");
        $_html .= sprintf("%s", $oBodyHTML);
        $_html .= sprintf("<script src='/js/function/sprintf.js'></script>\n");
        $_html .= sprintf("<script src='/js/client/json/cAjax.js'></script>\n");
        $_html .= sprintf("<script src='/js/ui/cLogger.js'></script>\n");
        $_html .= sprintf("<script src='/js/ui/cLoader.js'></script>\n");
        $_html .= sprintf("<script src='/js/ui/cLogin.js'></script>\n");
        $_html .= sprintf("<script src='/js/callback/cResponse.js'></script>\n");
        $_html .= sprintf("<script src='/js/callback/cLogger.js'></script>\n");
        $_html .= sprintf("<script src='/js/callback/cLogin.js'></script>\n");
        $_html .= sprintf("<script src='/js/callback/cCallback.js'></script>\n");
        $_html .= sprintf("<script src='/js/callback/callback.js'></script>\n");
        $_html .= sprintf("</body>\n");
        $_html .= sprintf("</html>\n");
    }

    private function initHtml(sHtml &$_sHtml): void
    {
        $_sHtml->title = "ReadyPHP | Connexion d'un utilisateur";
        $_sHtml->encoding = "UTF-8";
        $_sHtml->lang = "fr";
        $_sHtml->logo = "/data/img/logo.png";
        $_sHtml->mimeType = "image/png";
    }
}
...

Gestion du contenu d'une page HTML


// php\ui\cBody.php (Gérer le contenu d'une page HTML)
...
<?php

declare(strict_types=1);

namespace php\ui;

class cBody
{
    public function __construct() {}

    public function run(string &$_html): void
    {
        $_html .= sprintf("<div>\n");

        $this->drawLoggerPage($_html);
        $this->drawLoaderPage($_html);
        $this->drawLoginPage($_html);
        $this->drawAccountPage($_html);
        $this->drawForgotPasswordPage($_html);

        $_html .= sprintf("</div>\n");
    }

    private function drawLoggerPage(string &$_html): void
    {
        $oLoggerHTML = "";
        $oLogger = new cLogger();
        $oLogger->run($oLoggerHTML);
        $_html .= sprintf("%s", $oLoggerHTML);
    }

    private function drawLoaderPage(string &$_html): void
    {
        $oLoaderHTML = "";
        $oLoader = new cLoader();
        $oLoader->run($oLoaderHTML);
        $_html .= sprintf("%s", $oLoaderHTML);
    }

    private function drawLoginPage(string &$_html): void
    {
        $oLoginHTML = "";
        $oLogin = new cLogin();
        $oLogin->run($oLoginHTML);

        $_html .= sprintf("<div class='idBodyTab' data-name='login-page'>\n");
        $_html .= sprintf("%s", $oLoginHTML);
        $_html .= sprintf("</div>\n");
    }

    private function drawAccountPage(string &$_html): void
    {
        $oAccountHTML = "";
        $oAccount = new cAccount();
        $oAccount->run($oAccountHTML);

        $_html .= sprintf("<div class='idBodyTab' data-name='account-page'>\n");
        $_html .= sprintf("%s", $oAccountHTML);
        $_html .= sprintf("</div>\n");
    }

    private function drawForgotPasswordPage(string &$_html): void
    {
        $oForgotPasswordHTML = "";
        $oForgotPassword = new cForgotPassword();
        $oForgotPassword->run($oForgotPasswordHTML);

        $_html .= sprintf("<div class='idBodyTab' data-name='forgot-password-page'>\n");
        $_html .= sprintf("%s", $oForgotPasswordHTML);
        $_html .= sprintf("</div>\n");
    }
}
...

Gestion de la fenêtre popup des messages


// php\ui\cLogger.php (Gérer la fenêtre popup des messages)
...
<?php

declare(strict_types=1);

namespace php\ui;

class cLogger
{
    public function __construct() {}

    public function run(string &$_html): void
    {
        $_html .= sprintf("<div class='logger-page-01' id='idLogger'>\n");
        $_html .= sprintf("<div class='logger-page-02' id='idLoggerForm'>\n");
        $_html .= sprintf("<div class='logger-page-03'>\n");
        $_html .= sprintf("<span id='idLoggerTitle'>Messages d'erreurs</span>\n");
        $_html .= sprintf("<span class='logger-page-05'
        onclick='onCallback(\"logger\", \"on-close-logger\", this)'><i class='fa fa-times'></i></span>\n");
        $_html .= sprintf("</div>\n");
        $_html .= sprintf("<div class='logger-page-04' id='idLoggerMsg'>Bonjour tout le monde.\n");
        $_html .= sprintf("</div>\n");
        $_html .= sprintf("</div>\n");
        $_html .= sprintf("</div>\n");
    }
}
...

// Logger (Fiche des messages d'erreurs)
image.png

// Logger (Fiche des messages d'informations)
image.png

Gestion de la fenêtre popup du chargeur web


// php\ui\cLoader.php (Gérer la fenêtre popup du chargeur web)
...
<?php

declare(strict_types=1);

namespace php\ui;

class cLoader
{
    public function __construct() {}

    public function run(string &$_html): void
    {
        $_html .= sprintf("<div class='loader-page-01' id='idLoader'>\n");
        $_html .= sprintf("<div class='loader-page-02' id='idLoaderForm'>\n");
        $_html .= sprintf("<div class='loader-page-03'>\n");
        $_html .= sprintf("<div class='loader-page-04'>\n");

        $_html .= sprintf("<div class='loader-page-05'></div>\n");
        $_html .= sprintf("<span class='loader-page-06'>Loading...</span>\n");

        $_html .= sprintf("</div>\n");
        $_html .= sprintf("</div>\n");
        $_html .= sprintf("</div>\n");
        $_html .= sprintf("</div>\n");
    }
}
...

// Loader (Fiche du chargeur web)
image.png

Gestion de la page de connexion


// php\ui\cLogin.php (Gérer la page de connexion)
...
<?php

declare(strict_types=1);

namespace php\ui;

class cLogin
{
    public function __construct() {}

    public function run(string &$_html): void
    {
        $_html .= sprintf("<div class='login-page-01'>\n");
        $_html .= sprintf("<div class='login-page-02'>Connexion d'un utilisateur</div>\n");
        $_html .= sprintf("<div class='login-page-03'>\n");

        $this->drawVerticalSpacer($_html);
        $this->drawUsername($_html);
        $this->drawVerticalSpacer($_html);
        $this->drawPassword($_html);
        $this->drawVerticalSpacer($_html);
        $this->drawForgotPasswordLink($_html);
        $this->drawVerticalSpacer($_html);
        $this->drawVerticalSpacer($_html);
        $this->drawConnectionButton($_html);
        $this->drawVerticalSpacer($_html);
        $this->drawVerticalSpacer($_html);
        $this->drawSubscriptionLink($_html);
        $this->drawVerticalSpacer($_html);

        $_html .= sprintf("</div>\n");
        $_html .= sprintf("</div>\n");
    }

    private function drawVerticalSpacer(string &$_html): void
    {
        $_html .= sprintf("<div class='login-page-07'></div>\n");
    }

    private function drawUsername(string &$_html): void
    {
        $_html .= sprintf("<div class='login-page-04'>\n");
        $_html .= sprintf("<label for='login-username' class='login-page-05'>Nom d'utilisateur :</label>\n");
        $_html .= sprintf("<input type='text' id='login-username' class='login-page-06' placeholder='Entrez le nom d'utilisateur...'/>\n");
        $_html .= sprintf("</div>\n");
    }

    private function drawPassword(string &$_html): void
    {
        $_html .= sprintf("<div class='login-page-04'>\n");
        $_html .= sprintf("<label for='login-password' class='login-page-05'>Mot de passe :</label>\n");
        $_html .= sprintf("<input type='password' id='login-password' class='login-page-06' placeholder='Entrez le mot de passe...'/>\n");
        $_html .= sprintf("</div>\n");
    }

    private function drawConnectionButton(string &$_html): void
    {
        $_html .= sprintf("<div class='login-page-08'>\n");
        $_html .= sprintf("<button type='button'
        onclick='onCallback(\"login\", \"on-connect-user\", this)'>Se connecter</button>\n");
        $_html .= sprintf("</div>\n");
    }

    private function drawSubscriptionLink(string &$_html): void
    {
        $_html .= sprintf("<div class='login-page-09'>\n");
        $_html .= sprintf("<div>Vous n'avez pas encore de compte ?
        <strong class='login-page-10' onclick='onCallback(\"login\", \"on-login-page\", this, \"account-page\")'>Créer un compte</strong></div>\n");
        $_html .= sprintf("</div>\n");
    }

    private function drawForgotPasswordLink(string &$_html): void
    {
        $_html .= sprintf("<div class='login-page-11'>\n");
        $_html .= sprintf("<strong class='login-page-12'
        onclick='onCallback(\"login\", \"on-login-page\", this, \"forgot-password-page\")'>Vous avez oublié votre mot de passe ?</strong>\n");
        $_html .= sprintf("</div>\n");
    }
}
...

// Login (Fiche de connexion d'un utilisateur)
image.png

Gestion de la page de création d'un compte d'utilisateur


// php\ui\cAccount.php (Gérer la création d'un compte d'utilisateur)
...
<?php

declare(strict_types=1);

namespace php\ui;

class cAccount
{
    public function __construct() {}

    public function run(string &$_html): void
    {
        $_html .= sprintf("<div class='account-page-01'>\n");
        $_html .= sprintf("<div class='account-page-02'>Création d'un compte utilisateur</div>\n");
        $_html .= sprintf("<div class='account-page-03'>\n");

        $this->drawVerticalSpacer($_html);
        $this->drawUsername($_html);
        $this->drawVerticalSpacer($_html);
        $this->drawPassword($_html);
        $this->drawVerticalSpacer($_html);
        $this->drawConfirmPassword($_html);
        $this->drawVerticalSpacer($_html);
        $this->drawVerticalSpacer($_html);
        $this->drawAccountButton($_html);
        $this->drawVerticalSpacer($_html);
        $this->drawVerticalSpacer($_html);
        $this->drawConnexionLink($_html);
        $this->drawVerticalSpacer($_html);

        $_html .= sprintf("</div>\n");
        $_html .= sprintf("</div>\n");
    }

    private function drawVerticalSpacer(string &$_html): void
    {
        $_html .= sprintf("<div class='account-page-07'></div>\n");
    }

    private function drawUsername(string &$_html): void
    {
        $_html .= sprintf("<div class='account-page-04'>\n");
        $_html .= sprintf("<label for='idAccountUsername' class='account-page-05'>Nom d'utilisateur :</label>\n");
        $_html .= sprintf("<input type='text' id='idAccountUsername' class='account-page-06' placeholder='Entrez le nom d'utilisateur...'/>\n");
        $_html .= sprintf("</div>\n");
    }

    private function drawPassword(string &$_html): void
    {
        $_html .= sprintf("<div class='account-page-04'>\n");
        $_html .= sprintf("<label for='idAccountPassword' class='account-page-05'>Mot de passe :</label>\n");
        $_html .= sprintf("<input type='password' id='idAccountPassword' class='account-page-06' placeholder='Entrez le mot de passe...'/>\n");
        $_html .= sprintf("</div>\n");
    }

    private function drawConfirmPassword(string &$_html): void
    {
        $_html .= sprintf("<div class='account-page-04'>\n");
        $_html .= sprintf("<label for='idAccountConfirmPassword' class='account-page-05'>Confirmation :</label>\n");
        $_html .= sprintf("<input type='password' id='idAccountConfirmPassword' class='account-page-06' placeholder='Entrez le mot de passe...'/>\n");
        $_html .= sprintf("</div>\n");
    }

    private function drawAccountButton(string &$_html): void
    {
        $_html .= sprintf("<div class='account-page-08'>\n");
        $_html .= sprintf("<button type='button'
        onclick='onCallback(\"login\", \"on-create-account-user\", this)'>Créer votre compte</button>\n");
        $_html .= sprintf("</div>\n");
    }

    private function drawConnexionLink(string &$_html): void
    {
        $_html .= sprintf("<div class='login-page-09'>\n");
        $_html .= sprintf("<div>Vous avez déjà un compte ? <strong class='login-page-10'
        onclick='onCallback(\"login\", \"on-login-page\", this, \"login-page\")'>Se connecter</strong></div>\n");
        $_html .= sprintf("</div>\n");
    }
}
...

// Account (Fiche de création d'un compte d'utilisateur)
image.png

Gestion de la page de récupération du mot de passe


// php\ui\cForgotPassword.php (Gérer la récupération du mot de passe)
...
<?php

declare(strict_types=1);

namespace php\ui;

class cForgotPassword
{
    public function __construct() {}

    public function run(string &$_html): void
    {
        $_html .= sprintf("<div class='forgot-password-page-01'>\n");
        $_html .= sprintf("<div class='forgot-password-page-02'>Récupération d'un mot de passe utilisateur</div>\n");
        $_html .= sprintf("<div class='forgot-password-page-03'>\n");

        $this->drawVerticalSpacer($_html);
        $this->drawUsername($_html);
        $this->drawVerticalSpacer($_html);
        $this->drawVerticalSpacer($_html);
        $this->drawForgotPasswordButton($_html);
        $this->drawVerticalSpacer($_html);
        $this->drawVerticalSpacer($_html);
        $this->drawConnexionLink($_html);
        $this->drawVerticalSpacer($_html);

        $_html .= sprintf("</div>\n");
        $_html .= sprintf("</div>\n");
    }

    private function drawVerticalSpacer(string &$_html): void
    {
        $_html .= sprintf("<div class='forgot-password-page-07'></div>\n");
    }

    private function drawUsername(string &$_html): void
    {
        $_html .= sprintf("<div class='forgot-password-page-04'>\n");
        $_html .= sprintf("<label for='idForgotPasswordUser' class='forgot-password-page-05'>Nom d'utilisateur :</label>\n");
        $_html .= sprintf("<input type='text' id='idForgotPasswordUser' class='forgot-password-page-06' placeholder='Entrez le nom d'utilisateur...'/>\n");
        $_html .= sprintf("</div>\n");
    }

    private function drawForgotPasswordButton(string &$_html): void
    {
        $_html .= sprintf("<div class='forgot-password-page-08'>\n");
        $_html .= sprintf("<button type='button'
        onclick='onCallback(\"login\", \"on-forgot-password-user\", this)'>Envoyer</button>\n");
        $_html .= sprintf("</div>\n");
    }

    private function drawConnexionLink(string &$_html): void
    {
        $_html .= sprintf("<div class='forgot-password-page-09'>\n");
        $_html .= sprintf("<div>Vous avez déjà un compte ? <strong class='forgot-password-page-10'
        onclick='onCallback(\"login\", \"on-login-page\", this, \"login-page\")'>Se connecter</strong></div>\n");
        $_html .= sprintf("</div>\n");
    }
}
...

// ForgotPassword (Fiche de récupération du mot de passe)
image.png

Gestion de l'interface frontend JS



Gestion du point d'entrée des callbacks JS


// js\callback\callback.js (Gérer le point d'entrée des scripts JS)
...
"use strict";

function onCallback(_module, _method, _obj = null, _data = "") {
  const oCallback = new callback.cCallback();
  oCallback.run(_module, _method, _obj, _data);
}
...

Gestion de la façade des callbacks JS


// js\callback\cCallback.js (Gérer la façade des scripts JS)
...
"use strict";

var callback = callback || {};

callback.cCallback = class  {
    static DEF_MODULE_LOGIN = "login";
    static DEF_MODULE_LOGGER = "logger";

    constructor() {}

    run(_module, _method, _obj, _data) {
        if (_module == callback.cCallback.DEF_MODULE_LOGIN) {
            this.#onLogin(_module, _method, _obj, _data);
        } else if (_module == callback.cCallback.DEF_MODULE_LOGGER) {
            this.#onLogger(_module, _method, _obj, _data);
        } else {
            console.log("[Error]:Le module est inconnu.|module=%s|method=%s",_module, _method);
        }
    }

    #onLogin(_module, _method, _obj, _data) {
        const oLogin = new callback.cLogin();
        oLogin.run(_module, _method, _obj, _data);
    }

    #onLogger(_module, _method, _obj, _data) {
        const oLogger = new callback.cLogger();
        oLogger.run(_module, _method, _obj, _data);
    }
}
...

Gestion de la façade des messages popup JS


// js\callback\cLogger.js (Gérer la façade du chargeur web JS)
...
"use strict";

var callback = callback || {};

callback.cLogger = class  {
    static DEF_METHOD_ON_CLOSE_LOGGER = "on-close-logger";

    constructor() {}

    run(_module, _method, _obj, _data) {
        if (_method == callback.cLogger.DEF_METHOD_ON_CLOSE_LOGGER) {
            this.#onCloseLogger(_obj, _data);
        } else {
            console.log("[Error]:La méthode est inconnue.|module=%s|method=%s|data=%s", _module, _method, _data);
        }
    }

    #onCloseLogger(_obj, _data) {
        ui.cLogger.Instance().close();
    }
}
...

// Logger (Fiche des messages d'erreurs)
image.png

// Logger (Fiche des messages d'informations)
image.png

Gestion de la façade du système de connexion JS


// js\callback\cLogin.js (Gérer la façade du système de connexion JS)
...
"use strict";

var callback = callback || {};

callback.cLogin = class  {
    static DEF_METHOD_ON_LOGIN_PAGE = "on-login-page";
    static DEF_METHOD_ON_CONNECT_USER = "on-connect-user";
    static DEF_METHOD_ON_CREATE_ACCOUNT_USER = "on-create-account-user";
    static DEF_METHOD_ON_FORGOT_PASSWORD_USER = "on-forgot-password-user";

    constructor() {}

    run(_module, _method, _obj, _data) {
        if (_method == callback.cLogin.DEF_METHOD_ON_LOGIN_PAGE) {
            this.#onLoginPage(_module, _method, _obj, _data);
        } else if (_method == callback.cLogin.DEF_METHOD_ON_CONNECT_USER) {
            this.#onConnectUser(_module, _method, _obj, _data);
        } else if (_method == callback.cLogin.DEF_METHOD_ON_CREATE_ACCOUNT_USER) {
            this.#onCreateAccountUser(_module, _method, _obj, _data);
        } else if (_method == callback.cLogin.DEF_METHOD_ON_FORGOT_PASSWORD_USER) {
            this.#onForgotPasswordUser(_module, _method, _obj, _data);
        } else {
            console.log("[Error]:La méthode est inconnue.|module=%s|method=%s|data=%s", _module, _method, _data);
        }
    }

    #onLoginPage(_module, _method, _obj, _data) {
        ui.cLogin.Instance().openTab(_data);
    }

    #onConnectUser(_module, _method, _obj, _data) {
        const oUsername = document.querySelector("#login-username").value;
        const oPassword = document.querySelector("#login-password").value;
        const oParams = {
            module: _module,
            method: _method,
            username: oUsername,
            password: oPassword
        };

        const oAjax = new client.json.cAjax();
        oAjax.callServer(JSON.stringify(oParams), this.#onConnectUserCallback);
    }

    #onConnectUserCallback(_response) {
        const oResponse = new callback.cResponse(_response);
        if (oResponse.hasErrors())
        {
            ui.cLogger.Instance().showError(oResponse.statusMsg());
        }
        else {
            ui.cLogger.Instance().showInfo(oResponse.statusMsg());
        }
    }

    #onCreateAccountUser(_module, _method, _obj, _data) {
        const oUsername = document.querySelector("#idAccountUsername").value;
        const oPassword = document.querySelector("#idAccountPassword").value;
        const oConfirmPassword = document.querySelector("#idAccountConfirmPassword").value;
        const oParams = {
            module: _module,
            method: _method,
            username: oUsername,
            password: oPassword,
            confirmPassword: oConfirmPassword
        };

        const oAjax = new client.json.cAjax();
        oAjax.callServer(JSON.stringify(oParams), this.#onCreateAccountUserCallback);
    }

    #onCreateAccountUserCallback(_response) {
        const oResponse = new callback.cResponse(_response);
        if (oResponse.hasErrors())
        {
            ui.cLogger.Instance().showError(oResponse.statusMsg());
        }
        else {
            ui.cLogger.Instance().showInfo(oResponse.statusMsg());
        }
    }

    #onForgotPasswordUser(_module, _method, _obj, _data) {
        const oUsername = document.querySelector("#idForgotPasswordUser").value;
        const oParams = {
            module: _module,
            method: _method,
            username: oUsername,
        };

        const oAjax = new client.json.cAjax();
        oAjax.callServer(JSON.stringify(oParams), this.#onForgotPasswordUserCallback);
    }

    #onForgotPasswordUserCallback(_response) {
        const oResponse = new callback.cResponse(_response);
        if (oResponse.hasErrors())
        {
            ui.cLogger.Instance().showError(oResponse.statusMsg());
        }
        else {
            ui.cLogger.Instance().showInfo(oResponse.statusMsg());
        }
    }
}
...

// Login (Fiche de connexion d'un utilisateur)
image.png

// Account (Fiche de création d'un compte d'utilisateur)
image.png

// ForgotPassword (Fiche de récupération du mot de passe)
image.png

Gestion de la réponse du serveur PHP en JS


// js\callback\cResponse.js (Gérer la réponse du serveur PHP en JS)
...
"use strict";

var callback = callback || {};

callback.cResponse = class {
    static DEF_KEY_STATUS = "status";
    static DEF_KEY_STATUS_CODE = "code";
    static DEF_KEY_STATUS_MSG = "msg";
    static DEF_STATUS_CODE_ERROR = "error";
    static DEF_STATUS_MSG_ERROR = "Un problème a été rencontré.";
    static DEF_KEY_DATA = "data";

    #m_statusCode;
    #m_statusMsg;
    #m_respData;

    constructor(_response) {
        this.#initResponse();
        this.#loadResponse(_response);
    }

    #initResponse() {
        this.#m_statusCode = callback.cResponse.DEF_STATUS_CODE_ERROR;
        this.#m_statusMsg = callback.cResponse.DEF_STATUS_MSG_ERROR;
        this.#m_respData = {};
    }

    #loadResponse(_response) {
        try {
            const oResponse = JSON.parse(_response);
            const oStatus = oResponse[callback.cResponse.DEF_KEY_STATUS];
            this.#m_statusCode = oStatus[callback.cResponse.DEF_KEY_STATUS_CODE];
            this.#m_statusMsg = oStatus[callback.cResponse.DEF_KEY_STATUS_MSG];
            this.#m_respData = oResponse[callback.cResponse.DEF_KEY_DATA];
        } catch (error) {
            console.error("L'analyse de la réponse a échoué.|error=%s", error);
        }
    }

    hasErrors() { return (this.#m_statusCode == callback.cResponse.DEF_STATUS_CODE_ERROR); }
    statusCode() { return this.#m_statusCode; }
    statusMsg() { return this.#m_statusMsg; }
    respData() { return this.#m_respData; }
}
...

// Response (Fiche d'une réponse serveur PHP en cas d'erreur)
image.png

// Response (Fiche d'une réponse serveur PHP en cas de succès)
image.png

Gestion des appels asynchrones Ajax JS


// js\client\json\cAjax.js (la réponse du serveur PHP en JS)
...
"use strict";

var client = client || {};
client.json = client.json || {};

client.json.cAjax = class {
    constructor() {}

    callServer(_data, _callback = null) {
        const oXHR = new XMLHttpRequest();
        oXHR.onreadystatechange = function() {
            if (this.readyState == 4 && this.status == 200) {
                ui.cLoader.Instance().close();
                if (_callback) _callback(this.responseText);
                console.log("[Info]:Request=%s", _data);
                console.log("[Info]:Response=%s", this.responseText);
            }
        };

        const oMethod = "POST";
        const oUrl = "/php/callback/json/callback.php";
        const isAsync = true;
        const oUser = null;
        const oPassword = null;
        const oContentType = "application/json; charset=UTF-8";

        oXHR.open(oMethod, oUrl, isAsync, oUser, oPassword);
        oXHR.setRequestHeader("Content-Type", oContentType);
        oXHR.send(_data);
        ui.cLoader.Instance().show();
    }
};
...

// Ajax (Fiche d'une requête client JS en cas d'erreur)
image.png

// Ajax (Fiche d'une requête client JS en cas de succès)
image.png

Gestion de la logique métier du chargeur web JS


// js\ui\cLoader.js (Gérer la logique métier du chargeur web JS)
...
"use strict";

var ui = ui || {};

ui.cLoader = class {
    static m_instance = null;

    constructor() {}

    static Instance() {
        if (this.m_instance == null) {
            this.m_instance = new ui.cLoader();
        }
        return this.m_instance;
    }

    close() {
        const idLoader = document.querySelector("#idLoader");
        const idLoaderForm = document.querySelector("#idLoaderForm");

        idLoaderForm.classList.remove("idAnimateShow");
        idLoaderForm.classList.add("idAnimateHide");

        setTimeout(function() {
            idLoader.style.display = "none";
        }, 400);
    }

    show() {
        const idLoader = document.querySelector("#idLoader");
        const idLoaderForm = document.querySelector("#idLoaderForm");
        idLoaderForm.classList.remove("idAnimateHide");
        idLoaderForm.classList.add("idAnimateShow");
        idLoader.style.display = "block";
    }
};
...

// Loader (Fiche du chargeur web)
image.png

Gestion de la logique métier des messages popup JS


// js\ui\cLogger.js (Gérer la logique métier des messages popup JS)
...
"use strict";

var ui = ui || {};

ui.cLogger = class {
    static DEF_TITLE_MSG_ERROR = "Messages d'erreurs";
    static DEF_TITLE_MSG_INFO = "Messages d'informations";

    static m_instance = null;

    constructor() {}

    static Instance() {
        if (this.m_instance == null) {
            this.m_instance = new ui.cLogger();
        }
        return this.m_instance;
    }

    close() {
        const idLogger = document.querySelector("#idLogger");
        const idLoggerForm = document.querySelector("#idLoggerForm");

        idLoggerForm.classList.remove("idAnimateShow");
        idLoggerForm.classList.add("idAnimateHide");

        setTimeout(function() {
            idLogger.style.display = "none";
        }, 400);
    }

    showInfo(_msg) {
        const idLogger = document.querySelector("#idLogger");
        const idLoggerTitle = document.querySelector("#idLoggerTitle");
        const idLoggerMsg = document.querySelector("#idLoggerMsg");
        idLoggerTitle.innerHTML = ui.cLogger.DEF_TITLE_MSG_INFO;
        idLoggerMsg.innerHTML = _msg;

        const idLoggerForm = document.querySelector("#idLoggerForm");
        idLoggerForm.classList.remove("idAnimateHide");
        idLoggerForm.classList.add("idAnimateShow");
        idLogger.style.display = "block";
    }

    showError(_msg) {
        const idLogger = document.querySelector("#idLogger");
        const idLoggerTitle = document.querySelector("#idLoggerTitle");
        const idLoggerMsg = document.querySelector("#idLoggerMsg");
        idLoggerTitle.innerHTML = ui.cLogger.DEF_TITLE_MSG_ERROR;
        idLoggerMsg.innerHTML = _msg;

        const idLoggerForm = document.querySelector("#idLoggerForm");
        idLoggerForm.classList.remove("idAnimateHide");
        idLoggerForm.classList.add("idAnimateShow");
        idLogger.style.display = "block";
    }
};
...

// Logger (Fiche des messages d'erreurs)
image.png

// Logger (Fiche des messages d'informations)
image.png

Gestion de la logique métier du système de connexion JS


// js\ui\cLogin.js (Gérer la logique métier du système de connexion JS)
...
"use strict";

var ui = ui || {};

ui.cLogin = class {
    static DEF_DEFAULT_PAGE = "login-page";

    static m_instance = null;

    constructor() {}

    static Instance() {
        if (this.m_instance == null) {
            this.m_instance = new ui.cLogin();
        }
        return this.m_instance;
    }

    openTab(_name = ui.cLogin.DEF_DEFAULT_PAGE) {
        const idBodyTabs = document.querySelectorAll(".idBodyTab");
        for (const idBodyTab of idBodyTabs) {
            if (idBodyTab.dataset.name == _name) {
                idBodyTab.style.display = "block";
                continue;
            }
            idBodyTab.style.display = "none";
        }
    }
};

ui.cLogin.Instance().openTab();
...

// Login (Fiche de connexion d'un utilisateur)
image.png

// Account (Fiche de création d'un compte d'utilisateur)
image.png

// ForgotPassword (Fiche de récupération du mot de passe)
image.png

Gestion de l'interface backend PHP



Gestion du point d'entrée du backend


// php\callback\json\callback.php (Gérer le point d'entrée du backend)
...
<?php

declare(strict_types=1);

namespace php\callback\json;

require $_SERVER["DOCUMENT_ROOT"] . DIRECTORY_SEPARATOR . "php/autoload.php";
require $_SERVER["DOCUMENT_ROOT"] . DIRECTORY_SEPARATOR . "libs/logger/logger.php";
require $_SERVER["DOCUMENT_ROOT"] . DIRECTORY_SEPARATOR . "/libs/uuid/uuid.php";

$oCallback = new cCallback();
$oCallback->run();
...

Gestion de la façade du backend


// php\callback\json\cGallback.php (Gérer la façade du backend)
...
<?php

declare(strict_types=1);

namespace php\callback\json;

use libs\logger\Logger;

class cCallback
{
    const DEF_REQUEST_SIZE_MAX = 1 * 1024 * 1024; // 1 Mo
    const DEF_KEY_MODULE = "module";
    const DEF_KEY_METHOD = "method";
    const DEF_MODULE_LOGIN = "login";

    public function __construct() {}

    public function run(): void
    {
        $oRequest = file_get_contents("php://input");
        $oResponse = new cResponse();
        $oRequestSize = $_SERVER['CONTENT_LENGTH'];

        if ($oRequestSize < self::DEF_REQUEST_SIZE_MAX) {
            $oJSON = \json_decode($oRequest, true);

            if (\json_last_error() === JSON_ERROR_NONE) {
                $this->runJSON($oJSON, $oResponse);
            }
        }

        $oResponse->sendResponse();
    }

    private function runJSON($_reqJSON, cResponse &$_response): void
    {
        if (!isset($_reqJSON[self::DEF_KEY_MODULE])) {
            Logger::error("Le module n'est pas défini.");
            return;
        }
        if (!isset($_reqJSON[self::DEF_KEY_METHOD])) {
            Logger::error("Le method n'est pas définie.");
            return;
        }

        $oModule = $_reqJSON[self::DEF_KEY_MODULE];
        $oMethod = $_reqJSON[self::DEF_KEY_METHOD];

        if (empty($oModule)) {
            Logger::error("Le module est obligatoire.");
            return;
        }
        if (empty($oMethod)) {
            Logger::error("Le method est obligatoire.");
            return;
        }

        $this->runCallback($oModule, $oMethod, $_reqJSON, $_response);
    }

    private function runCallback(string $_module, string $_method, array $_reqJSON, cResponse &$_response): void
    {
        if ($_module == self::DEF_MODULE_LOGIN) {
            $this->onLogin($_module, $_method, $_reqJSON, $_response);
        } else {
            Logger::error(sprintf("Le module est inconnu.|module=%s|method=%s", $_module, $_method));
        }
    }

    private function onLogin(string $_module, string $_method, array $_reqJSON, cResponse &$_response): void
    {
        $oLogin = new cLogin();
        $oLogin->run($_module, $_method, $_reqJSON, $_response);
    }
}
...

Gestion de la façade du système de connexion


// php\callback\json\cLogin.php (Gérer la façade du système de connexion)
...
<?php

declare(strict_types=1);

namespace php\callback\json;

use libs\logger\Logger;

class cLogin
{
    const DEF_METHOD_ON_CONNECT_USER = "on-connect-user";
    const DEF_METHOD_ON_CREATE_ACCOUNT_USER = "on-create-account-user";
    const DEF_METHOD_ON_FORGOT_PASSWORD_USER = "on-forgot-password-user";
    const DEF_KEY_USERNAME = "username";
    const DEF_KEY_PASSWORD = "password";
    const DEF_KEY_CONFIRM_PASSWORD = "confirmPassword";

    public function __construct() {}

    public function run(string $_module, string $_method, array $_reqJSON, cResponse &$_response): void
    {
        if ($_method == self::DEF_METHOD_ON_CONNECT_USER) {
            $this->onConnectUser($_reqJSON, $_response);
        } else if ($_method == self::DEF_METHOD_ON_CREATE_ACCOUNT_USER) {
            $this->onCreateAccountUser($_reqJSON, $_response);
        } else if ($_method == self::DEF_METHOD_ON_FORGOT_PASSWORD_USER) {
            $this->onForgotPasswordUser($_reqJSON, $_response);
        } else if ($_method == self::DEF_METHOD_ON_CREATE_ACCOUNT_USER) {
            $this->onCreateAccountUser($_reqJSON, $_response);
        } else {
            Logger::error(sprintf("La méthode est inconnue.|module=%s|method=%s", $_module, $_method));
        }
    }

    private function onConnectUser(array $_reqJSON, cResponse &$_response): void
    {
        if (!isset($_reqJSON[self::DEF_KEY_USERNAME])) {
            Logger::error("Le nom d'utilisateur n'est pas défini.");
            return;
        }
        if (!isset($_reqJSON[self::DEF_KEY_PASSWORD])) {
            Logger::error("Le mot de passe n'est pas défini.");
            return;
        }

        $oUsername = $_reqJSON[self::DEF_KEY_USERNAME];
        $oPassword = $_reqJSON[self::DEF_KEY_PASSWORD];

        if (empty($oUsername)) {
            Logger::error("Le nom d'utilisateur est obligatoire.");
            return;
        }
        if (empty($oPassword)) {
            Logger::error("Le mot de passe est obligatoire.");
            return;
        }

        $oLogin = new \php\database\sqlite\cLogin();
        $oUuid = "";
        if (!$oLogin->connectUser($oUsername, $oPassword, $oUuid)) {
            return;
        }
        $_response->msgOK();
    }

    private function onCreateAccountUser(array $_reqJSON, cResponse &$_response): void
    {
        if (!isset($_reqJSON[self::DEF_KEY_USERNAME])) {
            Logger::error("Le nom d'utilisateur n'est pas défini.");
            return;
        }
        if (!isset($_reqJSON[self::DEF_KEY_PASSWORD])) {
            Logger::error("Le mot de passe n'est pas défini.");
            return;
        }
        if (!isset($_reqJSON[self::DEF_KEY_CONFIRM_PASSWORD])) {
            Logger::error("La confirmation du mot de passe n'est pas défini.");
            return;
        }

        $oUsername = $_reqJSON[self::DEF_KEY_USERNAME];
        $oPassword = $_reqJSON[self::DEF_KEY_PASSWORD];
        $oConfirmPassword = $_reqJSON[self::DEF_KEY_CONFIRM_PASSWORD];

        if (empty($oUsername)) {
            Logger::error("Le nom d'utilisateur est obligatoire.");
            return;
        }
        if (empty($oPassword)) {
            Logger::error("Le mot de passe est obligatoire.");
            return;
        }
        if (empty($oConfirmPassword)) {
            Logger::error("La confirmation du mot de passe est obligatoire.");
            return;
        }

        if ($oPassword != $oConfirmPassword) {
            Logger::error("Le mot de passe et sa confirmation sont différents.");
            return;
        }

        $oLogin = new \php\database\sqlite\cLogin();
        $oUuid = "";
        if (!$oLogin->createAccountUser($oUsername, $oPassword, $oUuid)) {
            return;
        }
        $_response->msgOK();
    }

    private function onForgotPasswordUser(array $_reqJSON, cResponse &$_response): void
    {
        if (!isset($_reqJSON[self::DEF_KEY_USERNAME])) {
            Logger::error("Le nom d'utilisateur n'est pas défini.");
            return;
        }

        $oUsername = $_reqJSON[self::DEF_KEY_USERNAME];

        if (empty($oUsername)) {
            Logger::error("Le nom d'utilisateur est obligatoire.");
            return;
        }

        $oLogin = new \php\database\sqlite\cLogin();
        $oUuid = "";
        if (!$oLogin->forgotPasswordtUser($oUsername, $oUuid)) {
            return;
        }
        $_response->msgOK();
    }
}
...

Gestion de la réponse du backend


// php\callback\json\cResponse.php (Gérer la réponse du backend)
...
<?php

declare(strict_types=1);

namespace php\callback\json;

class cResponse
{
    const DEF_KEY_STATUS = "status";
    const DEF_KEY_STATUS_CODE = "code";
    const DEF_KEY_STATUS_MSG = "msg";
    const DEF_KEY_DATA = "data";

    const DEF_STATUS_CODE_OK = "ok";
    const DEF_STATUS_CODE_ERROR = "error";
    const DEF_DEFAULT_MSG_ERROR = "Un problème a été rencontré.";
    const DEF_DEFAULT_MSG_OK = "La requête a bien été traitée.";

    private $m_statusCode;
    private $m_statusMsg;
    private $m_responseData;

    public function __construct()
    {
        $this->m_statusCode = self::DEF_STATUS_CODE_ERROR;
        $this->m_statusMsg = self::DEF_DEFAULT_MSG_ERROR;
        $this->m_responseData = array();
    }

    public function msgError($_msgError = self::DEF_DEFAULT_MSG_ERROR): void
    {
        $this->m_statusCode = self::DEF_STATUS_CODE_ERROR;
        $this->m_statusMsg = $_msgError;
    }

    public function msgOK($_msgOK = self::DEF_DEFAULT_MSG_OK): void
    {
        $this->m_statusCode = self::DEF_STATUS_CODE_OK;
        $this->m_statusMsg = $_msgOK;
    }

    public function responseData($_responseData): void
    {
        $this->m_responseData = $_responseData;
    }

    public function hasErrors(): bool
    {
        return ($this->m_statusCode == self::DEF_STATUS_CODE_ERROR);
    }

    public function sendResponse(): void
    {
        $oResponse = array();
        $oResponse[self::DEF_KEY_STATUS] = array();
        $oResponse[self::DEF_KEY_STATUS][self::DEF_KEY_STATUS_CODE] = $this->m_statusCode;
        $oResponse[self::DEF_KEY_STATUS][self::DEF_KEY_STATUS_MSG] = $this->m_statusMsg;
        $oResponse[self::DEF_KEY_DATA] = $this->m_responseData;
        //$oResponseText = \json_encode($oResponse, JSON_UNESCAPED_UNICODE | JSON_PRETTY_PRINT);
        $oResponseText = \json_encode($oResponse, JSON_UNESCAPED_UNICODE);
        echo $oResponseText;
    }
}
...

// Response (Fiche d'une réponse serveur PHP en cas d'erreur)
image.png

// Response (Fiche d'une réponse serveur PHP en cas de succès)
image.png

Gestion des accès à la base de données PHP



Gestion de l'accès à la base de données SQLite


// php\database\sqlite\cDatabase.php (Gérer l'accès à la base de données SQLite)
...
<?php

declare(strict_types=1);

namespace php\database\sqlite;

use libs\logger\Logger;

class cDatabase
{
    const DEF_DATABASE_PATH = "db/sqlite/db/database.dat";

    private $m_dbPath;

    public function __construct(string $_dbPath = "")
    {
        if (empty($_dbPath)) {
            $this->m_dbPath = $this->dbPath();
        } else {
            $this->m_dbPath = $_dbPath;
        }
    }

    public function execQuery(string $_sql, array $_params = array()): bool
    {
        try {
            $oPDO = null;
            if (!$this->open($oPDO)) {
                return false;
            }
            $oSTMT = $oPDO->prepare($_sql);
            if (!$oSTMT) {
                Logger::error(sprintf("La préparation de la requête SQL a échoué.|dbPath=%s", $this->m_dbPath));
                return false;
            }
            if (!$oSTMT->execute($_params)) {
                Logger::error(sprintf("L'exécution de la requête SQL a échoué.|dbPath=%s", $this->m_dbPath));
                return false;
            }
            return true;
        } catch (\Exception $e) {
            Logger::error(sprintf("L'exécution de la requête SQL a échoué.|dbPath=%s|error=%s", $this->m_dbPath, $e->getMessage()));
        }
        return false;
    }

    public function transactionQuery(string $_sql, callable $_callback, array $_params = array()): bool
    {
        try {
            $oPDO = null;
            if (!$this->open($oPDO)) {
                return false;
            }
            $dbPDO = new cDatabasePDO($oPDO, $this->m_dbPath);
            $dbPDO->beginTransaction();
            if (!$_callback($dbPDO, $_sql, $_params)) {
                Logger::error(sprintf("L'exécution du callback sur la transaction SQL a échoué.|dbPath=%s", $this->m_dbPath));
                $dbPDO->rollbackTransaction();
                return false;
            }
            $dbPDO->commitTransaction();
            return true;
        } catch (\Exception $e) {
            Logger::error(sprintf("L'exécution de la transaction SQL a échoué.|dbPath=%s|error=%s", $this->m_dbPath, $e->getMessage()));
        }
        return false;
    }

    public function loopQuery(string $_sql, callable $_callback, array $_params = array()): bool
    {
        try {
            $oPDO = null;
            if (!$this->open($oPDO)) {
                return false;
            }
            $oSTMT = $oPDO->prepare($_sql);
            if (!$oSTMT) {
                Logger::error(sprintf("La préparation de la requête SQL a échoué.|dbPath=%s", $this->m_dbPath));
                return false;
            }
            $dbSTMT = new cDatabaseSTMT($oPDO, $oSTMT, $this->m_dbPath);
            if (!$_callback($dbSTMT, $this->m_dbPath, $_params)) {
                Logger::error(sprintf("L'exécution du callback sur la requête SQL a échoué.|dbPath=%s", $this->m_dbPath));
                return false;
            }
            return true;
        } catch (\Exception $e) {
            Logger::error(sprintf("L'exécution de la requête SQL a échoué.|dbPath=%s|error=%s", $this->m_dbPath, $e->getMessage()));
        }
        return false;
    }

    public function readData(string $_sql, string &$_data, array $_params = array()): bool
    {
        try {
            $oPDO = null;
            if (!$this->open($oPDO)) {
                return false;
            }
            $oSTMT = $oPDO->prepare($_sql);
            if (!$oSTMT) {
                Logger::error(sprintf("La préparation de la requête SQL a échoué.|dbPath=%s", $this->m_dbPath));
                return false;
            }
            if (!$oSTMT->execute($_params)) {
                Logger::error(sprintf("L'exécution de la requête SQL a échoué.|dbPath=%s", $this->m_dbPath));
                return false;
            }
            $oResult = $oSTMT->fetchAll(\PDO::FETCH_ASSOC);
            foreach ($oResult as $oRow) {
                foreach ($oRow as $oValue) {
                    $_data = $oValue;
                    break;
                }
            }
            return true;
        } catch (\Exception $e) {
            Logger::error(sprintf("L'exécution de la requête SQL a échoué.|dbPath=%s|error=%s", $this->m_dbPath, $e->getMessage()));
        }
        return false;
    }

    public function readMap(string $_sql, array &$_dataMap, array $_params = array()): bool
    {
        try {
            $oPDO = null;
            if (!$this->open($oPDO)) {
                return false;
            }
            $oSTMT = $oPDO->prepare($_sql);
            if (!$oSTMT) {
                Logger::error(sprintf("La préparation de la requête SQL a échoué.|dbPath=%s", $this->m_dbPath));
                return false;
            }
            if (!$oSTMT->execute($_params)) {
                Logger::error(sprintf("L'exécution de la requête SQL a échoué.|dbPath=%s", $this->m_dbPath));
                return false;
            }
            $oResult = $oSTMT->fetchAll(\PDO::FETCH_ASSOC);
            $_dataMap = array();
            foreach ($oResult as $oRow) {
                $oDataRow = array();
                foreach ($oRow as $oValue) {
                    $oDataRow[] = $oValue;
                }
                $_dataMap[] = $oDataRow;
            }
            return true;
        } catch (\Exception $e) {
            Logger::error(sprintf("L'exécution de la requête SQL a échoué.|dbPath=%s|error=%s", $this->m_dbPath, $e->getMessage()));
        }
        return false;
    }

    private function open(\PDO|null &$_PDO): bool
    {
        try {
            $dbPath = sprintf("sqlite:%s", $this->m_dbPath);
            $_PDO = new \PDO($dbPath);
            $_PDO->setAttribute(\PDO::ATTR_DEFAULT_FETCH_MODE, \PDO::FETCH_ASSOC);
            $_PDO->setAttribute(\PDO::ATTR_ERRMODE, \PDO::ERRMODE_EXCEPTION);
            return true;
        } catch (\Exception $e) {
            Logger::error(sprintf("L'initialisation du module PDO a échoué.|dbPath=%s|error=%s", $dbPath, $e->getMessage()));
        }
        return false;
    }

    private function dbPath(): string
    {
        return $_SERVER['DOCUMENT_ROOT'] . DIRECTORY_SEPARATOR . self::DEF_DATABASE_PATH;
    }
}
...

Gestion de la transaction des données SQL (commit, rollback)


// php\database\sqlite\cDatabasePDO.php (Gérer la transaction des données SQL)
...
<?php

declare(strict_types=1);

namespace php\database\sqlite;

use libs\logger\Logger;

class cDatabasePDO
{
    private $m_PDO;
    private $m_dbPath;

    public function __construct(\PDO &$_PDO, string $_dbPath)
    {
        $this->m_PDO = &$_PDO;
        $this->m_dbPath = $_dbPath;
    }

    public function beginTransaction(): bool
    {
        try {
            return $this->m_PDO->beginTransaction();
        } catch (\Exception $e) {
            Logger::error(sprintf("Le démarrage de la transaction SQL a échoué.|dbPath=%s|error=%s", $this->m_dbPath, $e->getMessage()));
        }
        return false;
    }

    public function commitTransaction(): bool
    {
        try {
            return $this->m_PDO->commit();
        } catch (\Exception $e) {
            Logger::error(sprintf("Le commit de la transaction SQL a échoué.|dbPath=%s|error=%s", $this->m_dbPath, $e->getMessage()));
        }
        return false;
    }

    public function rollbackTransaction(): bool
    {
        try {
            return $this->m_PDO->rollback();
        } catch (\Exception $e) {
            Logger::error(sprintf("Le rollback de la transaction SQL a échoué.|dbPath=%s|error=%s", $this->m_dbPath, $e->getMessage()));
        }
        return false;
    }

    public function execQuery(string $_sql, array $_params = array()): bool
    {
        try {
            $oSTMT = $this->m_PDO->prepare($_sql);
            if (!$oSTMT) {
                Logger::error(sprintf("La préparation de la transaction SQL a échoué.|dbPath=%s", $this->m_dbPath));
                return false;
            }
            if (!$oSTMT->execute($_params)) {
                Logger::error(sprintf("L'exécution de la transaction SQL a échoué.|dbPath=%s", $this->m_dbPath));
                return false;
            }
            return true;
        } catch (\Exception $e) {
            Logger::error(sprintf("L'exécution de la transaction SQL a échoué.|dbPath=%s|error=%s", $this->m_dbPath, $e->getMessage()));
        }
        return false;
    }
}
...

Gestion des requêtes multiples préparées SQL (parameter binding)


// php\database\sqlite\cDatabaseSTMT.php (Gérer les requêtes multiples préparées SQL)
// [A faire en cas d'insertion multiples en base]

...
<?php

declare(strict_types=1);

namespace php\database\sqlite;

use libs\logger\Logger;

class cDatabaseSTMT
{
    private $m_PDO;
    private $m_STMT;
    private $m_dbPath;

    public function __construct(\PDO &$_PDO, \PDOStatement &$_STMT, $_dbPath)
    {
        $this->m_PDO = &$_PDO;
        $this->m_STMT = &$_STMT;
        $this->m_dbPath = $_dbPath;
    }
}
...

Gestion de l'accès aux données de connexion 


// php\database\sqlite\cLogin.php (Gérer l'accès aux données de connexion)
...
<?php

declare(strict_types=1);

namespace php\database\sqlite;

use libs\logger\Logger;

use function libs\uuid\uuid;

class cLogin
{
    public function __construct() {}

    public function connectUser(string $_username, string $_password, string &$_uuid): bool
    {
        if (!$this->loadUserUuid($_username, $_password, $_uuid)) {
            return false;
        }
        return true;
    }

    public function createAccountUser(string $_username, string $_password, &$_uuid): bool
    {
        if ($this->loadUserUuid($_username, $_password, $_uuid)) {
            Logger::warning(sprintf("L'utilisateur existe déjà.|username=%s", $_username));
            return false;
        }
        if (!$this->createUser($_username, $_password, $_uuid)) {
            return false;
        }
        return true;
    }

    public function forgotPasswordtUser(string $_username, string &$_uuid): bool
    {
        if (!$this->loadUnsernameUuid($_username, $_uuid)) {
            Logger::warning(sprintf("L'utilisateur n'existe pas encore.|username=%s", $_username));
            return false;
        }
        return true;
    }

    private function loadUserUuid(string $_username, string $_password, string &$_uuid): bool
    {
        $dbSQL = new cDatabase();
        $oSQL = "select _uuid from _user
        where _username = :username and _password = :password";
        $oParams = array(
            ":username" => $_username,
            ":password" => $_password
        );
        $oUuid = array();
        if (!$dbSQL->readMap($oSQL, $oUuid, $oParams)) {
            return false;
        }
        if (empty($oUuid)) {
            Logger::warning(sprintf("L'utilisateur n'existe pas encore.|username=%s", $_username));
            return false;
        }
        if (count(($oUuid)) > 1) {
            Logger::error(sprintf("Plusieurs utilisateurs possèdent le même nom d'utilisateur.|username=%s", $_username));
            return false;
        }
        $_uuid = $oUuid[0][0];
        return true;
    }

    private function loadUnsernameUuid(string $_username, string &$_uuid): bool
    {
        $dbSQL = new cDatabase();
        $oSQL = "select _uuid from _user
        where _username = :username";
        $oParams = array(
            ":username" => $_username
        );
        $oUuid = array();
        if (!$dbSQL->readMap($oSQL, $oUuid, $oParams)) {
            return false;
        }
        if (empty($oUuid)) {
            Logger::warning(sprintf("L'utilisateur n'existe pas encore.|username=%s", $_username));
            return false;
        }
        if (count(($oUuid)) > 1) {
            Logger::error(sprintf("Plusieurs utilisateurs possèdent le même nom d'utilisateur.|username=%s", $_username));
            return false;
        }
        $_uuid = $oUuid[0][0];
        return true;
    }

    private function createUser(string $_username, string $_password, string &$_uuid): bool
    {
        $_uuid = uuid();
        $dbSQL = new cDatabase();
        $oSQL = "insert into _user (_uuid, _username, _password)
        values (:uuid, :username, :password)";
        $oParams = array(
            ":uuid" => $_uuid,
            ":username" => $_username,
            ":password" => $_password
        );
        if (!$dbSQL->execQuery($oSQL, $oParams)) {
            return false;
        }
        return true;
    }
}
...

// Login (Fiche de connexion d'un utilisateur)
image.png

// Account (Fiche de création d'un compte d'utilisateur)
image.png

// ForgotPassword (Fiche de récupération du mot de passe)
image.png