Insertion, mise à Jour et suppression de données à l'aide de JDatabase

From Joomla! Documentation

Revision as of 17:50, 3 January 2021 by FuzzyBot (talk | contribs) (Updating to match new version of source page)
(diff) ← Older revision | Latest revision (diff) | Newer revision → (diff)
Other languages:
English • ‎Nederlands • ‎español • ‎français • ‎русский • ‎中文(台灣)‎
Joomla! 
3.x
Joomla! 
2.5
Note de version

Remarque : de nombreux exemples présentés ci-dessous utilisent $db->query() au lieu de $db->execute(). C'est une méthode ancienne utilisée dans Joomla! 1.5 et 2.5 et est un obsolète depuis Joomla! 3.x.

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 des données à partir d'une ou plusieurs tables et la récupération sous différentes formes.

Cette partie de la documentation va s'intéressée à l'insertion, la mise à jour et la suppression de données à partir d'une table de base de données. Pour comprendre la seconde partie, veuillez consulter : Sélectionner des données via JDatabase

Introduction

Joomla! propose un système sophistiqué de couche d'abstraction de base de données pour en simplifier l'utilisation par les développeurs d'extensions tierces. Les nouvelles versions de la Plateforme d'API Joomla! proposent des fonctionnalités supplémentaires qui permettent d'étendre encore plus la couche de base de données et inclues 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é des codes de connexion et pour simplifier le codage SQL.

Joomla permet l'utilisation de différents types de systèmes de base de données d'exécution SQL et peut être utilisé sur une grande variété d'environnements différents avec différents préfixes de table. En plus de ces fonctionnalités, la classe crée automatiquement la connexion à la base de données. Il suffit de deux lignes de code pour l'instanciation de l'objet dont vous avez et obtenir un résultat à partir de la base de données dans différents formats. Grace à la couche de base de données, Joomla assure un maximum de compatibilité et de flexibilité pour vos extensions.

La requête

L'interrogation de bases de données pour Joomla! a changé depuis l'introduction dans le Framework Joomla! du "chaînage de requêtes" qui est maintenant la méthode recommandée pour la construction de requêtes de base de données (bien que les requêtes de chaînes soient toujours prises en charge).

Le chaînage de requêtes fait référence à une méthode permettant la connexion à un certain nombre de méthodes, les unes après les autres où chaque méthode retournant un objet peut prendre en charge la nouvelle 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 JDatabaseDriver getQuery :

$db = JFactory::getDbo();

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

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

Pour interroger notre source de données, nous pouvons faire appel à un certain nombre de méthodes JDatabaseQuery. Ces méthodes vont encapsuler la requête des données sources (SQL) en cachant la syntaxe spécifique de la requête du développeur et augmenter ainsi la portabilité du code source du développeur.

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

Insertion d'un enregistrement

Utilisation de SQL

La classe JDatabaseQuery fournit un certain nombre de méthodes pour la construction de requêtes de type insert, les plus courantes étant :

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

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

// Insert columns.
$columns = array('user_id', 'profile_key', 'profile_value', 'ordering');

// Insert values.
$values = array(1001, $db->quote('custom.message'), $db->quote('Inserting a record using insert()'), 1);

// Prepare the insert query.
$query
    ->insert($db->quoteName('#__user_profiles'))
    ->columns($db->quoteName($columns))
    ->values(implode(',', $values));

// Set the query using our newly populated query object and execute it.
$db->setQuery($query);
$db->execute();

(Here the quoteName() function adds appropriate quotes around the table and column names to avoid conflicts with any database reserved word, now or in the future.) To get the ID of the row that you just inserted, you can use the 'insertid' method, for example.

// Get the row that was just inserted
$new_row_id = $db->insertid();

How to store empty value as NULL

If your default value of a column is NULL, you should not add that column name in the array. Let the database system store NULL as the default value. If the default value of a column is not NULL and it is allowed to store NULL values, you should specify that in the code. See how to do it in the following example.

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

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

/** First Case [NULL as default value] **/
// The column 'profile_value' has NULL as default value. So, we will not add it to the array. The database engine will store NULL as value for column 'profile_value'.
// $columns = array('user_id', 'profile_key', 'profile_value', 'ordering');
$columns = array('user_id', 'profile_key', 'ordering');

// Insert values.
$values = array(1001, $db->quote('custom.message'), 1);

/** Second Case [string as default value and you can also store NULL value] **/
// The column 'profile_value' has empty string '' as default value but we can also store NULL value. So, we have to add the column name and NULL value to $columns and $values.
$columns = array('user_id', 'profile_key', 'profile_value', 'ordering');

// Insert values.
$values = array(1001, $db->quote('custom.message'), $db->quote('NULL'), 1);

Utilisation d'un objet

La classe JDatabaseDriver fournit également une méthode pratique pour la sauvegarde d'un objet directement dans la base de données, nous autorisant à ajouter un enregistrement à une table sans avoir à écrire une seule ligne de SQL.

// Create and populate an object.
$profile = new stdClass();
$profile->user_id = 1001;
$profile->profile_key='custom.message';
$profile->profile_value='Inserting a record using insertObject()';
$profile->ordering=1;

// Insert the object into the user profile table.
$result = JFactory::getDbo()->insertObject('#__user_profiles', $profile);

Remarquez ici que nous n'avons pas besoin d'échapper le nom de la table, la méthode insertObject fait cela pour nous.

La méthode insertObject va générer une erreur si un problème se présente lors de l'insertion de l'enregistrement dans la table de base de données.

Si vous donnez vous-même une valeur à la clé primaire - valeur unique (comme dans l'exemple ci-dessus), il est recommandé que vous vérifiez que cette valeur n'est pas déjà utilisée en exécutant un select dans cette table avec cette valeur de clé primaire avant de de tenter un ajout.

Si vous ajoutez simplement une ligne de plus dans votre table (i.e. que la base génère elle-même la clé primaire), vous pouvez indiquer le nom correspondant à la colonne de la clé primaire dans l'objet en tant que troisième paramètre de la méthode insertObject() ; la méthode va alors mettre à jour l'objet qui vient d'être créé avec la valeur de la clé primaire.

Par exemple, en utilisant la ligne suivante :

$result = $dbconnect->insertObject('#__my_table', $object, 'primary_key');

après exécution, $object->primary_key va être mis à jour avec la valeur de la clé primaire de la ligne qui vient d'être insérée.

ASTUCE : Mettre $object->primary_key à null ou 0 (zéro) avant de réaliser l'insertion pour pouvoir détecter si la valeur a été mise à jour.

How to store empty value as NULL when insert an object

If your default value of a column is NULL, you should not add that column name to the object. Let the database system store NULL as the default value. If the default value of a column is not NULL and it is allowed to store NULL values, you should specify that in the code. See how to do it in the following example.

// Create and populate an object.
$profile = new stdClass();
$profile->user_id = 1001;
$profile->profile_key='custom.message';
$profile->ordering=1;

/** First Case [NULL as default value] **/
// The column 'profile_value' has NULL as default value. So, we will not add it to the object. The database engine will store NULL as value for column 'profile_value'.
// $profile->profile_value='Inserting a record using insertObject()';

/** Second Case [string as default value and you can also store NULL value] **/
// The column 'profile_value' has empty string '' as default value but we can also store NULL value. So, we have to add the column name and NULL value as its value.
$profile->profile_value = $db->quote('NULL');

// Insert the object into the user profile table.
$result = JFactory::getDbo()->insertObject('#__user_profiles', $profile);

Mise à jour d'un enregistrement

Utilisation de SQL

La classe JDatabaseQuery fournit également des méthodes pour construire des requêtes de mise à jour, en particulier update et set. Nous réutilisons également une autre méthode que nous avons utilisée lors de la création d'instructions select à savoir : la méthode where.

$db = JFactory::getDbo();

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

// Fields to update.
$fields = array(
    $db->quoteName('profile_value') . ' = ' . $db->quote('Updating custom message for user 1001.'),
    $db->quoteName('ordering') . ' = 2',

    // If you would like to store NULL value, you should specify that.
    $db->quoteName('avatar') . ' = NULL',
);

// Conditions for which records should be updated.
$conditions = array(
    $db->quoteName('user_id') . ' = 42', 
    $db->quoteName('profile_key') . ' = ' . $db->quote('custom.message')
);

$query->update($db->quoteName('#__user_profiles'))->set($fields)->where($conditions);

$db->setQuery($query);

$result = $db->execute();


Utilisation d'un objet

Comme pour insertObject, la classe JDatabaseDriver fournit une méthode pratique pour la mise à jour d'un objet.

Ci-dessous, nous allons mettre à jour notre table personnalisée avec de nouvelles valeurs à l'aide d'une ID de clé primaire existante :

$updateNulls = true;

// Create an object for the record we are going to update.
$object = new stdClass();

// Must be a valid primary key value.
$object->id = 1;
$object->title = 'My Custom Record';
$object->description = 'A custom record being updated in the database.';

// If you would like to store NULL value, you should specify that.
$object->short_description = null;

// Update their details in the users table using id as the primary key.
// You should provide forth parameter with value TRUE, if you would like to store the NULL values.
$result = JFactory::getDbo()->updateObject('#__custom_table', $object, 'id', $updateNulls);

Tout comme insertObject, updateObject va s'occuper d'échapper les noms de table à notre place.

La méthode updateObject va générer une erreur si un problème se présente lors de la mise à jour de l'enregistrement dans la table de base de données.

Nous devons nous assurer que l'enregistrement existe déjà avant de tenter de le mettre à jour, de sorte que nous souhaiterions probablement ajouter certaines vérifications de données avant de procéder à l'exécution de la méthode updateObject.

Suppression d'un enregistrement

Enfin, il existe également la méthode de suppression delete pour supprimer des enregistrements de la base de données.

$db = JFactory::getDbo();

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

// delete all custom keys for user 1001.
$conditions = array(
    $db->quoteName('user_id') . ' = 1001', 
    $db->quoteName('profile_key') . ' = ' . $db->quote('custom.%')
);

$query->delete($db->quoteName('#__user_profiles'));
$query->where($conditions);

$db->setQuery($query);

$result = $db->execute();

Sample Module Code

Below is the code for a simple Joomla module which you can install and run to demonstrate use of the JDatabase functionality for updating records in the database, and which you can adapt to experiment with some of the concepts described above. If you are unsure about development and installing a Joomla module then following the tutorial at Creating a simple module will help. Important note: In any Joomla extensions which you develop that you should avoid accessing the core Joomla tables directly like this and should instead use the Joomla APIs if at all possible, because the database structures may change without warning. In a folder mod_db_update create the following 2 files:

mod_db_update.xml

<?xml version="1.0" encoding="utf-8"?>
<extension type="module" version="3.1" client="site" method="upgrade">
    <name>Database update demo</name>
    <version>1.0.1</version>
    <description>Code demonstrating use of Joomla Database class to perform SQL UPDATE statements</description>
    <files>
        <filename module="mod_db_update">mod_db_update.php</filename>
    </files>
</extension>

mod_db_update.php

<?php
defined('_JEXEC') or die('Restricted Access');

use Joomla\CMS\Factory;

$db = Factory::getDbo();

$me = Factory::getUser();

if ($me->id == 0)
{
	echo "Not logged on!";
}
else
{
	$email = $me->email; 
	// change the case of the email address
	$email_uppercase = strtoupper($email);
	if ($email == $email_uppercase)
	{
		$new_email = strtolower($email);
	}
	else
	{
		$new_email = $email_uppercase;
	}
	
	$query = $db->getQuery(true);

	$fields = array($db->quoteName('email') . " = '{$new_email}'");

	$conditions = array($db->quoteName('id') . ' = ' . $me->id); 

	$query->update($db->quoteName('#__users'))->set($fields)->where($conditions);

	echo $db->replacePrefix((string) $query);
	
	$db->setQuery($query);

	if ($result = $db->execute())
	{
		echo "Email case successfully changed!";
	}
}

The code above updates the email address field in the users record of the currently logged-on user, toggling between upper case and lower case in successive reloads of the web page. The method Factory::getUser() returns the user object of the currently logged-on user, or if not logged on, then a blank user object, whose id field is set to zero. The $db->replacePrefix((string) $query) expression returns the actual SQL statement, and outputting this can be useful in debugging.

Zip up the mod_db_update directory to create mod_db_update.zip.

Within your Joomla administrator go to Install Extensions and via the Upload Package File tab upload this zip file to install this sample log module.

Make this module visible by editing it (click on it within the Modules page) then:

  1. making its status Published
  2. selecting a position on the page for it to be shown
  3. on the menu assignment tab specify the pages it should appear on

When you visit a site web page then you should see the module in your selected position, and it should output the SQL UPDATE statement and affirm that it has updated the record successfully. To confirm that it has updated the record correctly go into phpmyadmin and view the users table within the Joomla database. The updates aren't visible via the admin Users functionality on the back end, as Joomla displays in lower case all the email addresses in the records.