Sélection de données en utilisant JDatabase

From Joomla! Documentation

This page is a translated version of the page Selecting data using JDatabase and the translation is 100% complete.

Other languages:
English • ‎español • ‎français • ‎Nederlands • ‎русский • ‎中文(中国大陆)‎ • ‎中文(台灣)‎
Joomla! 
3.x
Joomla! 
2.5
Note de version

Remarquez que de nombreux exemples cités utilisent $db->query() au lieu de $db->execute(). C'était une méthode ancienne dans Joomla! 1.5 et 2.5 qui va émettre un message d'obsolescence à partir de Joomla 3.0+.

Ce didacticiel est divisé en deux parties indépendantes :

  • L'insertion, la mise à jour et la suppression de données de la base de données.
  • La sélection de données à partir d'une ou plusieurs tables et la récupération sous différentes formes.

Cette section de la documentation se focalise sur la sélection de données à partir d'une table de la base de données et la récupère dans différents formats. Pour voir l'autre partie cliquez ici

Introduction

Joomla! fournit une couche d'abstraction sophistiquée de base de données pour en simplifier l'utilisation pour les développeurs tierces. Les nouvelles versions de l'API de la Plateforme Joomla! fournissent des fonctionnalités supplémentaires qui permettent d'étendre encore plus la couche de base de données et d'inclure des fonctionnalités telles que des connecteurs pour une plus grande variété de serveurs de base de données ou encore le chaînage de requêtes pour améliorer la lisibilité du code de connexion et simplifier le codage SQL.

Joomla peut utiliser différentes sortes de systèmes de base de données SQL et s'exécuter dans des environnements variés avec différents préfixes de table. En plus de ces fonctions, la classe (JDatabase) crée automatiquement la connexion à la base de données. Il suffit de deux lignes de code lors de l'instanciation de l'objet pour obtenir un résultat à partir de la base de données dans différents formats. L'utilisation de la couche de base de données Joomla assure un maximum de compatibilité et de flexibilité pour vos extensions.

La Requête

Faire une requête dans la base de données Joomla a changé avec l'introduction de Joomla 1.6. Le moyen recommandé pour construire des requêtes de base de données se fait via le "chaînage de requêtes" (même si les requêtes en chaînes de caractères sont encore supportées).

Le chaînage de requête fait référence à une méthode se connectant à un nombre de méthodes, les unes après les autres, où chaque méthode retourne un objet supportant la prochaine méthode, améliorant ainsi la lisibilité et la simplification du code.

Pour obtenir une nouvelle instance de la classe JDatabaseQuery, nous utilisons la méthode getQuery de la classe JDatabaseDriver:

$db = JFactory::getDbo();

$query = $db->getQuery(true);

JDatabaseDriver::getQuery prend un argument optionnel, $new, qui peut être true (vrai) ou false (faux) (la valeur par défaut est false).

Pour interroger notre source de données, nous pouvons appeler un nombre de méthodes de la classe JDatabaseQuery; ces méthodes encapsulent le langage de requête de la source de données (dans la plupart des cas SQL), en occultant la syntaxe de requête spécifique au développeur et en augmentant la portabilité du code source du développeur.

Les méthodes les plus fréquemment utilisées incluent; select, from, join, where et order. Il y a aussi des méthodes comme insert, update et delete pour modifier des enregistrements dans la base de données. En chaînant ces appels de méthodes à d'autres, vous pouvez créer presque n'importe quelle requête à votre base de données sans compromettre la portabilité de votre code..

Sélectionner des enregistrements d'une seule table

Ci-dessous se trouve un exemple de création de requête de base de données utilisant la classe JDatabaseQuery. En utilisant les méthodes select, from, where et order, nous pouvons créer des requêtes flexibles, facilement lisibles et portable:

// Get a db connection.
$db = JFactory::getDbo();

// Create a new query object.
$query = $db->getQuery(true);

// Select all records from the user profile table where key begins with "custom.".
// Order it by the ordering field.
$query->select($db->quoteName(array('user_id', 'profile_key', 'profile_value', 'ordering')));
$query->from($db->quoteName('#__user_profiles'));
$query->where($db->quoteName('profile_key') . ' LIKE '. $db->quote('\'custom.%\''));
$query->order('ordering ASC');

// Reset the query using our newly populated query object.
$db->setQuery($query);

// Load the results as a list of stdClass objects (see later for more options on retrieving data).
$results = $db->loadObjectList();

La requête peut également être chaînée pour la simplifier davantage :

$query
    ->select($db->quoteName(array('user_id', 'profile_key', 'profile_value', 'ordering')))
    ->from($db->quoteName('#__user_profiles'))
    ->where($db->quoteName('profile_key') . ' LIKE '. $db->quote('\'custom.%\''))
    ->order('ordering ASC');

Le chaînage peut devenir utile quand des requêtes deviennent plus longues et plus complexes.

Le groupement peut également être réalisé simplement. La requête suivante compterait le nombre d'articles dans chaque catégorie.

$query
    ->select( array('catid', 'COUNT(*)') )
    ->from($db->quoteName('#__content'))
    ->group($db->quoteName('catid'));

Une limite peut être définie pour une requête en utilisant setLimit. Par exemple, dans la requête suivante, jusqu'à 10 enregistrements seront retournés.

$query
    ->select($db->quoteName(array('user_id', 'profile_key', 'profile_value', 'ordering')))
    ->from($db->quoteName('#__user_profiles'))
    ->setLimit('10');

Sélectionner des enregistrements de plusieurs tables

En utilisant les méthodes de jointure de JDatabaseQuery, on peut sélectionner des enregistrements de multiples tables reliées. La méthode générique "join" prend deux arguments; le "type" de jointure (inner, outer, left, right) et la condition de jointure. Dans l'exemple suivant vous remarquerez que l'on peut utiliser tous les mots-clés qu'on utiliserait normalement si on écrivait une requête SQL native, incluant le mot-clé AS pour donner un surnom aux tables et le mot-clé ON pour créer des relations entre les tables. Remarquez aussi que le surnom de la table est utilisé dans toutes les méthodes qui font référence aux colonnes de la table (c-a-d select, where, order).

// Get a db connection.
$db = JFactory::getDbo();

// Create a new query object.
$query = $db->getQuery(true);

// Select all articles for users who have a username which starts with 'a'.
// Order it by the created date.
// Note by putting 'a' as a second parameter will generate `#__content` AS `a`
$query
    ->select(array('a.*', 'b.username', 'b.name'))
    ->from($db->quoteName('#__content', 'a'))
    ->join('INNER', $db->quoteName('#__users', 'b') . ' ON (' . $db->quoteName('a.created_by') . ' = ' . $db->quoteName('b.id') . ')')
    ->where($db->quoteName('b.username') . ' LIKE ' . $db->quote('a%'))
    ->order($db->quoteName('a.created') . ' DESC');

// Reset the query using our newly populated query object.
$db->setQuery($query);

// Load the results as a list of stdClass objects (see later for more options on retrieving data).
$results = $db->loadObjectList();

La méthode de jointure ci-dessus nous permet d'interroger les deux tables "content" et "users", en récupérant les articles avec leur auteur. Il y a aussi des méthodes pratiques pour les jointures:

Nous pouvons utiliser plusieurs jointures pour interroger plus de deux tables :

$query
    ->select(array('a.*', 'b.username', 'b.name', 'c.*', 'd.*'))
    ->from($db->quoteName('#__content', 'a'))
    ->join('INNER', $db->quoteName('#__users', 'b') . ' ON (' . $db->quoteName('a.created_by') . ' = ' . $db->quoteName('b.id') . ')')
    ->join('LEFT', $db->quoteName('#__user_profiles', 'c') . ' ON (' . $db->quoteName('b.id') . ' = ' . $db->quoteName('c.user_id') . ')')
    ->join('RIGHT', $db->quoteName('#__categories', 'd') . ' ON (' . $db->quoteName('a.catid') . ' = ' . $db->quoteName('d.id') . ')')
    ->where($db->quoteName('b.username') . ' LIKE ' . $db->quote('a%'))
    ->order($db->quoteName('a.created') . ' DESC');

Remarquez comment le chaînage rend le code source plus lisible pour ces longues requêtes.

Dans certains cas, vous aurez aussi besoin d'utiliser la clause AS lors de la sélection d'éléments pour éviter des conflits de nom de colonne. Dans ce cas, plusieurs déclarations "select" peuvent être chaînées en conjonction de l'utilisation de $db->quoteName dans le second paramètre.

$query
    ->select('a.*')
    ->select($db->quoteName('b.username', 'username'))
    ->select($db->quoteName('b.name', 'name'))
    ->from($db->quoteName('#__content', 'a'))
    ->join('INNER', $db->quoteName('#__users', 'b') . ' ON (' . $db->quoteName('a.created_by') . ' = ' . $db->quoteName('b.id') . ')')
    ->where($db->quoteName('b.username') . ' LIKE ' . $db->quote('a%'))
    ->order($db->quoteName('a.created') . ' DESC');

Un second tableau peut aussi être utilisé comme deuxième paramètre de la déclaration de "select" pour alimenter les valeurs de la clause AS. Souvenez-vous d'inclure des "nulls" dans le second tableau aux colonnes correspondantes du premier tableau pour lesquelles vous ne voulez pas utiliser la clause AS:

$query
    ->select(array('a.*'))
    ->select($db->quoteName(array('b.username', 'b.name'), array('username', 'name')))
    ->from($db->quoteName('#__content', 'a'))
    ->join('INNER', $db->quoteName('#__users', 'b') . ' ON (' . $db->quoteName('a.created_by') . ' = ' . $db->quoteName('b.id') . ')')
    ->where($db->quoteName('b.username') . ' LIKE ' . $db->quote('a%'))
    ->order($db->quoteName('a.created') . ' DESC');


Résultats de requête

La classe JDatabase possède plusieurs méthodes pour travailler avec un jeu de résultat d'une requête.

Résultat à valeur simple

loadResult()

Utilisez loadResult() quand vous souhaitez juste une seule valeur de retour de votre requête de base de données.

id nom email nom d'utilisateur
1 John Smith johnsmith@domaine.exemple johnsmith
2 Magda Hellman magda_h@domaine.exemple magdah
3 Yvonne de Gaulle ydg@domaine.exemple ydegaulle

C'est souvent le résultat d'une requête de "comptage" pour obtenir un nombre d'enregistrements:

$db = JFactory::getDbo();
$query = $db->getQuery(true);
$query->select('COUNT(*)');
$query->from($db->quoteName('#__my_table'));
$query->where($db->quoteName('name')." = ".$db->quote($value));

// Reset the query using our newly populated query object.
$db->setQuery($query);
$count = $db->loadResult();

ou quand vous souhaitez juste un seul champ d'une seule ligne de la table (ou un seul champ à partir de la première ligne retournée).

$db = JFactory::getDbo();
$query = $db->getQuery(true);
$query->select('field_name');
$query->from($db->quoteName('#__my_table'));
$query->where($db->quoteName('some_name')." = ".$db->quote($some_value));

$db->setQuery($query);
$result = $db->loadResult();


Résultats à une simple ligne

Chacune de ces fonctions de résultats va retourner un seul enregistrement de la base de données même s'il peut y avoir plusieurs enregistrements correspondant au critère donné. Pour obtenir plus d'enregistrements vous devez encore appeler la fonction.

id nom email nom d'utilisateur
1 John Smith johnsmith@domaine.exemple johnsmith
2 Magda Hellman magda_h@domaine.exemple magdah
3 Yvonne de Gaulle ydg@domaine.exemple ydegaulle

loadRow()

loadRow() retourne un tableau indexé d'un seul enregistrement dans la table:

. . .
$db->setQuery($query);
$row = $db->loadRow();
print_r($row);

donnera :

Array ( [0] => 1, [1] => John Smith, [2] => johnsmith@domain.example, [3] => johnsmith ) 
Vous pouvez accéder individuellement aux valeurs en faisant:
$row['index'] // e.g. $row['2']

Remarques :

  1. Les indices du tableau sont des nombres débutant à zéro.
  2. Bien que vous pouvez répéter l'appel pour obtenir d'autres lignes, une des fonctions retournant plusieurs lignes peut être plus utile.

loadAssoc()

loadAssoc() retourne un tableau associatif d'un seul enregistrement dans la table:

. . .
$db->setQuery($query);
$row = $db->loadAssoc();
print_r($row);

donnera:

Array ( [id] => 1, [name] => John Smith, [email] => johnsmith@domain.example, [username] => johnsmith )
Vous pouvez accéder individuellement aux valeurs en faisant:
$row['name'] // e.g. $row['email']
  1. Bien que vous pouvez répéter l'appel pour obtenir d'autres lignes, une des fonctions retournant plusieurs lignes peut être plus utile.

loadObject()

loadObject retourne un objet PHP d'un seul enregistrement dans la table:

. . .
$db->setQuery($query);
$result = $db->loadObject();
print_r($result);

donnera:

stdClass Object ( [id] => 1, [name] => John Smith, [email] => johnsmith@domain.example, [username] => johnsmith )
Vous pouvez accéder individuellement aux valeurs en faisant:
$result->index // e.g. $result->email
  1. Bien que vous pouvez répéter l'appel pour obtenir d'autres lignes, une des fonctions retournant plusieurs lignes peut être plus utile.

Résultats à une simple colonne

Chacune de ces fonctions de résultats va retourner une seule colonne de la base de données.

id nom email nom d'utilisateur
1 John Smith johnsmith@domaine.exemple johnsmith
2 Magda Hellman magda_h@domaine.exemple magdah
3 Yvonne de Gaulle ydg@domaine.exemple ydegaulle

loadColumn()

loadColumn() retourne un tableau indexé d'un seul enregistrement dans la table:

$query->select('name'));
      ->from . . .";
. . .
$db->setQuery($query);
$column= $db->loadColumn();
print_r($column);

donnera :

Array ( [0] => John Smith, [1] => Magda Hellman, [2] => Yvonne de Gaulle )
Vous pouvez accéder individuellement aux valeurs en faisant:
$column['index'] // e.g. $column['2']

A savoir:

  1. Les indices du tableau sont des nombres débutant à zéro.
  2. loadColumn() est équivalent à loadColumn(0).

loadColumn($index)

loadColumn($index) retourne un tableau indexé d'une seule colonne dans la table:

$query->select(array('name', 'email', 'username'));
      ->from . . .";
. . .
$db->setQuery($query);
$column= $db->loadColumn(1);
print_r($column);

donnera:

Array ( [0] => johnsmith@domain.example, [1] => magda_h@domain.example, [2] => ydg@domain.example )
Vous pouvez accéder individuellement aux valeurs en faisant:
$column['index'] // e.g. $column['2']

loadColumn($index) vous permet d'itérer à travers une série de colonnes dans les résultats

. . .
$db->setQuery($query);
for ( $i = 0; $i <= 2; $i++ ) {
  $column= $db->loadColumn($i);
  print_r($column);
}

donnera :

Array ( [0] => John Smith, [1] => Magda Hellman, [2] => Yvonne de Gaulle ),
Array ( [0] => johnsmith@domain.example, [1] => magda_h@domain.example, [2] => ydg@domain.example ),
Array ( [0] => johnsmith, [1] => magdah, [2] => ydegaulle )

A savoir:

  1. Les indices du tableau sont des nombres débutant à zéro.

Résultats Multi-Ligne

Chacune de ces fonctions de résultats va retourner plusieurs enregistrements de la base de données.

id name email nom d'utilisateur
1 John Smith johnsmith@domain.example johnsmith
2 Magda Hellman magda_h@domain.example magdah
3 Yvonne de Gaulle ydg@domain.example ydegaulle

loadRowList()

loadRowList() retourne un tableau indexé de tableaux indexés à partir des enregistrements de la table retourné par la requête:

. . .
$db->setQuery($query);
$row = $db->loadRowList();
print_r($row);

donnera (avec les retours à la ligne pour la lisibilité):

Array ( 
[0] => Array ( [0] => 1, [1] => John Smith, [2] => johnsmith@domain.example, [3] => johnsmith ), 
[1] => Array ( [0] => 2, [1] => Magda Hellman, [2] => magda_h@domain.example, [3] => magdah ), 
[2] => Array ( [0] => 3, [1] => Yvonne de Gaulle, [2] => ydg@domain.example, [3] => ydegaulle ) 
)
Vous pouvez accéder individuellement aux lignes en faisant:
$row['index'] // e.g. $row['2']
Vous pouvez accéder individuellement aux valeurs en faisant:
$row['index']['index'] // e.g. $row['2']['3']

A savoir:

  1. Les indices du tableau sont des nombres débutant à zéro.

loadAssocList()

loadAssocList() retourne un tableau indexé de tableaux associatifs à partir des enregistrements de la table retournés par la requête:

. . .
$db->setQuery($query);
$row = $db->loadAssocList();
print_r($row);

donnera (avec les retours à la ligne pour la lisibilité):

Array ( 
[0] => Array ( [id] => 1, [name] => John Smith, [email] => johnsmith@domain.example, [username] => johnsmith ), 
[1] => Array ( [id] => 2, [name] => Magda Hellman, [email] => magda_h@domain.example, [username] => magdah ), 
[2] => Array ( [id] => 3, [name] => Yvonne de Gaulle, [email] => ydg@domain.example, [username] => ydegaulle ) 
) 
Vous pouvez accéder individuellement aux lignes en faisant:
$row['index'] // e.g. $row['2']
Vous pouvez accéder individuellement aux valeurs en faisant:
$row['index']['column_name'] // e.g. $row['2']['email']

loadAssocList($key)

loadAssocList('clé') retourne un tableau associatif - indexé sur 'clé' - des tableaux associatifs à partir des enregistrements de la table retournés par la requête:

. . .
$db->setQuery($query);
$row = $db->loadAssocList('username');
print_r($row);

donnera (avec les retours à la ligne pour la lisibilité):

Array ( 
[johnsmith] => Array ( [id] => 1, [name] => John Smith, [email] => johnsmith@domain.example, [username] => johnsmith ), 
[magdah] => Array ( [id] => 2, [name] => Magda Hellman, [email] => magda_h@domain.example, [username] => magdah ), 
[ydegaulle] => Array ( [id] => 3, [name] => Yvonne de Gaulle, [email] => ydg@domain.example, [username] => ydegaulle ) 
)
Vous pouvez accéder individuellement aux lignes en faisant:
$row['key_value'] // e.g. $row['johnsmith']
et vous pouvez accéder individuellement aux valeurs en faisant:
$row['key_value']['column_name'] // e.g. $row['johnsmith']['email']

A savoir: clé doit être un nom de colonne valide de la table; il ne doit pas être un index ou une clé primaire. Mais s'il n'a pas de valeur unique vous ne pourrez pas extraire les résultats fidèlement.

loadAssocList($key, $column)

loadAssocList('key', 'column') retourne un tableau associatif, indexé sur 'key', de valeurs de la colonne nommée 'column' retournés par la requête:

. . .
$db->setQuery($query);
$row = $db->loadAssocList('id', 'username');
print_r($row);

donnera (avec les retours à la ligne pour la lisibilité):

Array ( 
[1] => John Smith, 
[2] => Magda Hellman, 
[3] => Yvonne de Gaulle,
)

A savoir: Key doit être un nom de colonne valide de la table; il ne doit pas être un index ou une clé primaire. Mais s'il n'a pas de valeur unique vous ne pourrez pas extraire les résultats fidèlement.

loadObjectList()

loadObjectList() retourne un tableau indexé d'objets PHP à partir des enregistrements de la table retournés par la requête:

. . .
$db->setQuery($query);
$row = $db->loadObjectList();
print_r($row);

donnera (avec les retours à la ligne pour la lisibilité):

Array ( 
[0] => stdClass Object ( [id] => 1, [name] => John Smith, 
    [email] => johnsmith@domain.example, [username] => johnsmith ), 
[1] => stdClass Object ( [id] => 2, [name] => Magda Hellman, 
    [email] => magda_h@domain.example, [username] => magdah ), 
[2] => stdClass Object ( [id] => 3, [name] => Yvonne de Gaulle, 
    [email] => ydg@domain.example, [username] => ydegaulle ) 
)
Vous pouvez accéder individuellement aux lignes en faisant:
$row['index'] // e.g. $row['2']
et vous pouvez accéder individuellement aux valeurs en faisant:
$row['index']->name // e.g. $row['2']->email

loadObjectList($key)

loadObjectList('key') retourne un tableau associatif - indexé sur 'key' - d'objets à partir des enregistrements de la table retournés par la requête:

. . .
$db->setQuery($query);
$row = $db->loadObjectList('username');
print_r($row);

donnera (avec les retours à la ligne pour la lisibilité):

Array ( 
[johnsmith] => stdClass Object ( [id] => 1, [name] => John Smith, 
    [email] => johnsmith@domain.example, [username] => johnsmith ), 
[magdah] => stdClass Object ( [id] => 2, [name] => Magda Hellman, 
    [email] => magda_h@domain.example, [username] => magdah ), 
[ydegaulle] => stdClass Object ( [id] => 3, [name] => Yvonne de Gaulle, 
    [email] => ydg@domain.example, [username] => ydegaulle ) 
)
Vous pouvez accéder individuellement aux lignes en faisant:
$row['key_value'] // e.g. $row['johnsmith']
et vous pouvez accéder individuellement aux valeurs en faisant:
$row['key_value']->column_name // e.g. $row['johnsmith']->email

A savoir: Key doit être un nom de colonne valide de la table; il ne doit pas être un index ou une clé primaire. Mais s'il n'a pas de valeur unique vous ne pourrez pas extraire les résultats fidèlement.

Méthodes de jeu de résultat divers

getNumRows()

getNumRows() retournera le nombre de lignes résultantes trouvées par la dernière requête SELECT ou SHOW et en attente d'être lue. Pour obtenir un résultat à partir de getNumRows(), vous devez l'exécuter après la requête et avant d'extraire tout résultat. Pour extraire le nombre de lignes affectées par une requête INSERT, UPDATE, REPLACE ou DELETE, utilisez getAffectedRows().

. . .
$db->setQuery($query);
$db->execute();
$num_rows = $db->getNumRows();
print_r($num_rows);
$result = $db->loadRowList();
retournera :
3

A savoir: getNumRows() est seulement valide pour des déclarations comme SELECT ou SHOW qui retourne un véritable jeu de résultats. Si vous exécutez getNumRows() après loadRowList() - ou n'importe quelle méthode d'extraction - vous obtiendrez un avertissement PHP.

Warning: mysql_num_rows(): 80 is not a valid MySQL result resource 
in libraries\joomla\database\database\mysql.php on line 344

Voir aussi