iGalerie

Documentation d'iGalerie 3

Gestionnaire de base de données

Les classes DB et DBLayer

Le gestionnaire de base de données a été pensé pour être le plus simple possible à utiliser. Il consiste en une classe principale nommée DB qui se trouve dans le fichier includes/core/DB.class.php. L'accès aux méthodes de cette classe se fait uniquement de manière statique.

DB est une classe héritée de la classe DBLayer :

class DB extends DBLayer 

La classe DBLayer correspond au type de base de données utilisé (MySQL, PostgreSQL ou SQLite). Concrétement, cela signifie qu'il existe trois classes DBLayer différentes qui correspondent à chaque type de base de données. Ces classes se trouvent dans le répertoire includes/core/dblayer/ et la classe DBLayer correspondant au type de base de données définit à l'installation sera chargée au tout début du fichier DB.class.php :

require_once(__DIR__ . '/dblayer/' . CONF_DB_TYPE . '.class.php');

Le principe est le suivant : toutes les requêtes SQL doivent être écrites dans la syntaxe MySQL. Ensuite, la méthode _replaceSQL() de la classe DBLayer se charge, via de simples rechercher-remplacer, de convertir cette syntaxe dans celle de la base de données utilisée.

Par exemple, supposons que l'on utilise une requête de type INSERT IGNORE. Si la base de données est SQLite, alors l'expression INSERT IGNORE (syntaxe MySQL) sera remplacée par INSERT OR IGNORE (syntaxe SQLite). Si on utilise la fonction RAND() (syntaxe MySQL), alors celle-ci sera remplacée par RANDOM() (syntaxe SQLite), etc.

Établir une connexion à la base de données

Pour établir une connexion à la base de données, il faut utiliser la méthode connect() :

DB::connect();

Cette méthode n'accepte aucun argument et utilise les paramètres de base de données situés dans le fichier de configuration config/conf.php. Ces paramètres sont placés dans des constantes ayant comme préfixe CONF_DB_. La méthode connect() retourne TRUE en cas de succès, FALSE en cas d'échec.

En supposant que vous souhaitez créer un script demandant une connexion à la base de donnée et situé dans le répertoire d'iGalerie, ce script devra ressembler à ça :

<?php

require_once(__DIR__ . '/includes/prepend.php');

// Connexion à la base de données.
if (!DB::connect())
{
   die('Impossible de se connecter à la base de données.');
}

?>

Le fichier prepend.php se chargera d'inclure automatiquement toutes les classes du noyau d'iGalerie (celles se trouvant dans le répertoire includes/core/) appelées par la suite. Il met également en place un gestionnaire d'erreur bien pratique pour le débogage. Quand une erreur PHP ou de base de données survient, celle-ci sera enregistrée dans le répertoire errors sous forme de fichier .xml et accessible dans la section Incidents de l'interface d'administration. Donc, si votre script ne fonctionne pas, le premier réflexe est d'aller dans cette section pour voir s'il n'y a pas un message d'erreur qui pourrait vous aidez à résoudre votre problème.

Effectuer des requêtes SQL

Toutes les requêtes SQL (SELECT, UPDATE, DELETE, etc.) passent par une seule méthode : DB::execute(). Cette méthode accepte cinq arguments, mais seul le premier, une chaîne qui correspond à la requête SQL, est indispensable. Elle renvoie TRUE en cas de succès et FALSE en cas d'échec.

execute(string $sql, $params = [], array $seq = [], array &$fetch = [], bool $fetch_not_null = FALSE): bool
Préfixe de table

A l'installation d'iGalerie, il est possible de choisir le préfixe des tables de la base de données pour MySQL et PostgreSQL. Ce préfixe sera enregistré dans la constante CONF_DB_PREF du fichier de configuration. Normalement, on devrait utiliser ce préfixe de cette manière :

$sql = 'SELECT * FROM ' . CONF_DB_PREF . 'categories WHERE cat_id = 5';

Si nous voulions écrire le nom de la table directement avec son préfixe, cela donnerait ceci ("igal3_" étant le préfixe par défaut pour MySQL) :

$sql = 'SELECT * FROM igal3_categories WHERE cat_id = 5';

Pour simplifier les choses et éviter de devoir utiliser cette constante dans toutes les requêtes SQL, il est possible (et même recommandé) d'utiliser cette syntaxe :

$sql = 'SELECT * FROM {categories} WHERE cat_id = 5';

En entourant le nom de la table avec des accolades, celles-ci seront remplacées par le préfixe de table par le gestionnaire de base de données. Cette syntaxe est plus courte et plus lisible que l'utilisation d'une constante.

Utilisation des méthodes execute() et fetch*()

Voici maintenant un exemple permettant d'effectuer une requête SELECT et d'en récupérer le résultat :

$sql = 'SELECT * FROM {categories} WHERE cat_id = 5';
if (!DB::execute($sql))
{
   // En cas d'échec, affiche un message d'erreur de la base de données.
   die(DB::getError());
}
$category = DB::fetchRow();

Pour récupérer les informations d'une requête de type SELECT ou SHOW, on utilisera l'une de ces quatre méthodes : DB::fetchVal(), DB::fetchCol(), DB::fetchRow() ou DB::fetchAll().

Méthode fetchVal()

La méthode fetchVal() sera préférée lorsque le résultat attendu est une donnée unique :

if (DB::execute('SELECT 3 * 5'))
{
   $result = DB::fetchVal(); // $result = 15
}

Cette méthode retournera la valeur attendue, ou bien NULL s'il n'y a aucun résultat.

Méthode fetchRow()

Pour récupérer une ligne entière dans une table, on utilisera la méthode fetchRow(), qui retournera un tableau associatif :

$sql = 'SELECT * FROM {categories} WHERE cat_id = 5';
if (DB::execute($sql))
{
   $category = DB::fetchRow(); // $category = ['cat_id' => 5, etc.];
}
Méthode fetchCol()

Pour récupérer la valeur d'une seule colonne de plusieurs enregistrements, on utilisera la méthode fetchCol() en indiquant le nom de la colonne comme argument :

$sql = 'SELECT cat_name FROM {categories} WHERE parent_id = 1 AND cat_id > 1';
if (DB::execute($sql))
{
   $albums = DB::fetchCol('cat_name'); // $category = [0 => 'Titre album', etc.];
}
Méthode fetchAll()

Et enfin, pour récupérer les valeurs de plusieurs colonnes pour plusieurs enregistrements, on utilisera la méthode fetchAll() :

$sql = 'SELECT cat_id, cat_name FROM {categories} ORDER BY cat_crtdt DESC LIMIT 10';
if (DB::execute($sql))
{
   $categories = DB::fetchAll(); // $categories = [0 => ['cat_id' => 5, 'cat_name' => 'Titre catégorie'], etc.];
}

Cette méthode accepte deux arguments : le premier est le nom d'une colonne et, utilisé seul, permet d'indexer les résultats sur la valeur de cette colonne. Quant au second argument, il permet de générer un tableau associatif "valeur de $col1 => valeur de $col2", dans le cas où seules les valeurs de deux colonnes sont à récupérer :

$sql = 'SELECT cat_id, cat_name FROM {categories} ORDER BY cat_crtdt DESC LIMIT 10';
if (DB::execute($sql))
{
   $categories = DB::fetchAll('cat_id', 'cat_name'); // $categories = [5 => 'Titre catégorie', etc.];
}

Requêtes préparées

La méthode execute() du gestionnaire de base de données permet l'utilisation des requêtes préparées avec le second paramètre $params.

Les requêtes préparées sont très importantes en matière de sécurité pour prévenir les injections SQL et doivent être utilisées de préférence chaque fois que l'on utilise des données dans une requête SQL qui ne sont pas écrites en dur dans le code (données en provenance d'un formulaire, d'un paramètre GET, d'un fichier, etc.).

Voici un exemple de requête préparée avec des paramètres nommés :

$sql = 'UPDATE {items} SET item_desc = :desc WHERE item_id = :id';
$params = ['desc' => 'Description', 'id' => 1];
if (!DB::execute($sql, $params))
{
   die(DB::getError());
}

Et la même chose avec des marqueurs :

$sql = 'UPDATE {items} SET item_desc = ? WHERE item_id = ?';
$params = ['Description', 1];
if (!DB::execute($sql, $params))
{
   die(DB::getError());
}

Pour effectuer une requête préparée avec des paramètres différents, il suffit d'utiliser un tableau multidimensionnel de paramètres :

$sql = 'UPDATE {items} SET item_desc = ? WHERE item_id = ?';
$params =
[
   ['Description', 1],
   ['Description', 2],
   ['Description', 3]
];
if (!DB::execute($sql, $params))
{
   die(DB::getError());
}

A l'inverse, si vous souhaitez n'utiliser qu'un seul paramètre dans une requête, vous pouvez passer directement la valeur de ce paramètre dans le second argument de la méthode execute() :

$sql = 'UPDATE {items} SET item_desc = ? WHERE item_id = 1';
if (!DB::execute($sql, 'Description'))
{
   die(DB::getError());
}

Dernière modification : 18/03/2024