Raccourcis : Contenu - rubriques - sous rubriques
EN FR
La page correspondant à la dernière version stable est consultable dans le Manuel Jelix 1.8

Jelix possède un système d'accès abstrait aux bases de données : jDb. jDb propose donc une API commune à toutes les bases de données. Pour le moment, les drivers fournis sont ceux pour :

  • mysql
  • postgresql
  • sqlite
  • oracle (oci)

Il y a aussi un autre driver, pdo, permettant d'indiquer à jDb d'utiliser pdo plutôt que les classes d'abstractions internes de jDb.

Si dans la liste ci-dessus, il n'y a pas le driver correspondant à votre base de données et que vous n'avez pas PDO, vous pouvez créer votre propre driver pour jDb.

À noter que bien que jDb soit une API commune à toutes les bases de données, ce n'est en aucun cas une classe qui adaptera les requêtes en fonction des bases de données. Aussi, faites attention à ne pas trop utiliser des spécificités SQL d'une base de données précise dans vos modules, si vous souhaitez qu'ils puissent être réutilisés dans d'autres projets qui n'utiliseront pas la même base.

Profils et configuration

Pour pouvoir accéder à une base de données, il faut d'abord indiquer les paramètres de connexion dans un fichier de configuration. Ce fichier est par défaut dbprofils.ini.php situé dans var/config/. Vous pouvez en avoir un avec un nom différent, il faut alors indiquer ce nom dans le fichier de configuration principal de votre application.

Vous pouvez définir plusieurs connexions, que l'on nomme "profiles". Ainsi vous pouvez définir des connexions pour la base de production, la base de développement par exemple, ou encore les différentes bases sur lesquelles s'appuie votre application.

Voici un exemple de fichier dbprofils.ini.php :


default = foo

[foo]
driver="mysql"
database="jelix"
host= "localhost"
user= "jelix"
password= "jelix"
persistent= on
force_encoding=true

Il y a une section "foo". Chaque section correspond à un profil de connexion. Un paramètre, "default", indique le profil à utiliser par défaut.

Dans une section, vous voyez un certain nombre de paramètres, dont quelques-un sont utilisables pour tous les drivers :

  • driver indique le driver à utiliser. Le nombre et le nom des autres paramètres diffèrent en fonction du driver utilisé.
  • table_prefix : permet d'indiquer un préfixe de table. Lors de l'utilisation d'un DAO avec un profil spécifiant ce paramètre, les tables indiquées dans le DAO sont préfixées dynamiquement par cette valeur. Lors de l'écriture manuelle de requêtes pour jDb, vous pouvez préfixer vos tables en fonction du profil utilisé grâce à la méthode prefixTable() de jDbConnection. Cette méthode prend en paramètre le nom de la table à préfixer.

profil mysql

Paramètres possibles :

  • driver : doit valoir "mysql"
  • database : le nom de la base de données à utiliser
  • host : le nom du serveur mysql sur lequel se connecter
  • user et password : le login/mot de passe pour la connexion
  • persistent : indique si la connexion est persistante (on) ou pas (off)
  • force_encoding : indique s'il faut spécifier le charset utilisé dans l'application, de manière à récupérer les données avec le bon charset. En effet, certains serveurs sont configurés par exemple par défaut avec une connexion en iso-8859-1, même si les données stockées sont en utf-8. Mettez à true si vous voyez que vous n'arrivez pas à afficher les données correctement.

profil postgresql

Paramètres possibles :

  • driver : doit valoir "pgsql"
  • database : le nom de la base de données à utiliser
  • host : le nom du serveur postgresql sur lequel se connecter. Si vous le mettez à vide, la connexion se fera via une socket unix.
  • port : indique le port de connexion. N'indiquez pas ce paramètre si vous voulez utiliser le port par défaut.
  • user et password : le login/mot de passe pour la connexion. Ne mettez pas ces paramètres si vous voulez utiliser le login/mot de passe par défaut (indiqués par exemple dans les variables d'environnement du système).
  • persistent : indique si la connexion est persistante (on) ou pas (off)
  • force_encoding : indique s'il faut spécifier le charset utilisé dans l'application, de manière à récupérer les données avec le bon charset. même explication que pour mysql.
  • timeout : Nombre de secondes autorisées pour l'établissement de la connexion au serveur avant de générer un timeout
  • single_transaction : Toutes les requêtes d'une même page seront envoyées au serveur au sein d'un même transaction (entre un BEGIN; et un COMMIT;) (on) ou non (off). Défaut: off
  • search_path : indiquer la liste des schémas dans lequel il faut chercher les tables, si le schéma par défaut pour la connexion ne correspond pas à celui dans lequel l'application va chercher.

profil sqlite

Paramètres possibles :

  • driver : doit valoir "sqlite"
  • database : le nom du fichier de base de données à utiliser
  • persistent : indique si la connexion est persistante (on) ou pas (off)

A noter que les fichiers de base de données sqlite doivent être déposés dans le répertoire : var/db/sqlite/ de votre application et qu'à la fois ce répertoire et le fichier de base de données sqlite doivent avoir les droits de lecture/écriture adéquats (ceux du serveur web).

Profil pdo

Paramètres possibles :

  • driver : doit valoir "pdo"
  • dsn : contient des informations de connexion (type de base de donnée, serveur, nom de la base..). Le format doit être celui attendu par PDO (voir la doc de pdo sur php.net).
  • user et password : le login/mot de passe pour la connexion. Ne mettre ces paramètres que si nécessaire.
  • force_encoding : indique s'il faut spécifier le charset utilisé dans l'application, de manière à récupérer les données avec le bon charset. même explication que pour mysql, et ce paramètre n'est pour le moment valable que pour mysql et postgresql.

[bar]
driver=pdo
dsn= "mysql:host=localhost;dbname=test"
user=
password=

Profil virtuel

jDb offre la possibilité d'utiliser un profil qui n'existe pas dans le fichier dbprofils. Cela permet de se connecter à une base de données dont on ne connaît pas les caractéristiques à l'avance.

Pour cela, avant d'appeler les différentes méthodes de jDb, il vous faut déclarer ce profil "virtuel". Vous appellerez donc la méthode createVirtualProfile, à laquelle vous donnerez un nom de profil, ainsi qu'un tableau de paramètres, ces paramètres étant les mêmes que décrits précédemment.


   $params = array(
       'driver'=>'mysql',
       'host'=>'localhost',
       'database'=>'jelix',
       'user'=>'toto',
       'password'=>'blabla',
       'persistent'=>'false',
       'force_encoding'=>true
   );
   jDb::createVirtualProfile('mon_profil', $params);

   $cnx = jDb::getConnection('mon_profil');
   // etc., voir la suite

Faire des requêtes

Une fois le fichier de configuration écrit, vous pouvez accéder aux bases de données.

La première chose à faire est de récupérer un objet jDbConnection :


  $cnx = jDb::getConnection();

La méthode getConnection() permet de récupérer un objet de type jDbConnection (ou jDbPDOConnection héritant de PDO, si vous utilisez PDO, ils ont toutefois la même API). Cette méthode accepte un paramètre facultatif : le nom du profil à utiliser. s'il n'est pas indiqué, celui déclaré par défaut sera utilisé.

Pour construire les requêtes, vous avez une méthode importante à connaître : quote(), qui permet d'échapper certains caractères dans les valeurs que vous voulez insérer dans vos requêtes. Elle évite dans une certaine mesure les problèmes comme l'injection SQL.


  $sql = "INSERT INTO users (nom,prenom) VALUES";
  $sql .=" (". $cnx->quote("de l'ombre") .",".$cnx->quote('robert').")";

Notez que la méthode quote() encadre la valeur avec des quotes.

Pour exécuter des requêtes, il y a principalement deux méthodes, exec et query.

exec

exec doit être utilisé pour les requêtes qui ne renvoient pas de résultat (UPDATE, INSERT, DELETE...). cette méthode renvoie juste le nombre de lignes concernées par la requête. Exemple :


  $cnx = jDb::getConnection();

  $cnx->exec("INSERT INTO users (nom,prenom) VALUES('dupont','toto')");

query

query est fait pour les requêtes qui renvoient des résultats, vides ou pas (SELECT ou procédures stockées). La méthode renvoie alors un objet jDbResultSet.

Voici un exemple rapide :


  $cnx = jDb::getConnection();

  $rs = $cnx->query('SELECT nom, prenom FROM users');
  $result='';
  while($record = $rs->fetch()){
     $result.='nom = '.$record->nom.' prenom='.$record->prenom."\n";
  } 

limitQuery

Vous pouvez faire des requêtes qui récupèrent un nombre limité d'enregistrements. Vous utiliserez alors la méthode limitQuery :


  $cnx = jDb::getConnection();

  $rs = $cnx->limitQuery('SELECT nom, prenom FROM users', 5,10);
  $result='';
  while($record = $rs->fetch()){
     $result.='nom = '.$record->nom.' prenom='.$record->prenom."\n";
  }

Le premier paramètre est la requête. Le deuxième est le numéro, dans la liste des résultats, du premier enregistrement à récupérer. Le troisième paramètre est le nombre d'enregistrements à récupérer.

ResultSet

jDbResultSet est l'objet que vous récupérez après avoir fait un SELECT (query ou limitQuery).

Sa méthode fetch() vous permet de récupérer un à un les enregistrements. À noter que jDbResultSet renvoie toujours un enregistrement sous forme d'objet.

Sa méthode fetchAll() permet de récupérer tout d'un coup dans un tableau PHP.

jDbResultSet implémente l'interface Iterator. De ce fait, vous pouvez utiliser cet objet dans certaines boucles, comme les foreach :


  $cnx = jDb::getConnection();

  $rs = $cnx->query('SELECT nom, prenom FROM users');
  $result='';
  foreach( $rs as $record){
     $result.='nom = '.$record->nom.' prenom='.$record->prenom."\n";
  } 

Les objets contenant les enregistrements sont des objets "anonymes" (ils n'ont pas de classe précise). Si vous voulez que ce soient des objets d'une certaine classe, vous devez l'indiquer via setFetchMode :


  class User {
    ...
  }

  $cnx = jDb::getConnection();

  $rs = $cnx->query('SELECT nom, prenom FROM users');
  $rs->setFetchMode($rs->FETCH_CLASS , 'User');
  $result='';
  foreach( $rs as $record){
     // $record est ici un objet de type User
     $result.='nom = '.$record->nom.' prenom='.$record->prenom."\n";
  } 

Pour le reste des méthodes, voyez la documentation de référence.

Utilisation dans un template

Il est possible de passer un objet jDbResultSet dans un template.

Dans le contrôleur :


  $cnx = jDb::getConnection();

  $rs = $cnx->query('SELECT nom, prenom FROM users');

  $template->assign('resultats', $rs);

Dans le template :


  <table>
    <tr> <th>nom</th> <th>prenom</th></tr>
  {foreach $resultats as $user}
    <tr> 
       <td>{$user->nom|escxml}</td>
       <td>{$user->prenom|escxml}</td>
    </tr>
  {/foreach}
   </table>

Transactions

jDb permet de faire des transactions. Bien sûr, il faut que le driver utilisé supporte les transactions.

Pour marquer le début d'une transaction, vous appellerez la méthode beginTransaction (). Ensuite vous lancerez les requêtes, Puis après avoir fait vos requêtes, vous pourrez valider la transaction en appelant la méthode commit(). Pour annuler une transaction, il suffit d'appeler rollback().


   $cnx = jDb::getConnection();

   $cnx->beginTransaction();

   $cnx->exec(...);
   $cnx->query(...);
   //....
   
   if($ok)
     $cnx->commit();
   else
     $cnx->rollback();

jDbWidget

jDbWidget est une classe fournissant des méthodes utiles.


  $dbw = jDb::getDbWidget(); // au lieu de getConnection()

  $record = $dbw->fetchFirst("SELECT nom, prenom FROM user");
  
  $liste = $dbw->fetchAll("SELECT nom, prenom FROM user");

Pour le reste des méthodes, voyez la documentation de référence.