Avez-vous une question? (216) 97 656 803 hajjriadh@gmail.com
Flutter

Maîtriser les Opérations CRUD avec sqflite dans Flutter

Un cours complet pour maîtriser Maîtriser les Opérations CRUD avec sqflite dans Flutter.

0 chapitres 0 QCM Accès gratuit

Maîtriser les Opérations CRUD avec sqflite dans Flutter

  1. Que'st-ce que Database CRUD ?

    • "CRUD" est un acronyme couramment utilisé dans le domaine de l'informatique, en particulier lorsqu'il s'agit de bases de données. Il signifie :
      • C: Create (Créer)
      • R: Read (Lire)
      • U: Update (Mettre à jour)
      • D: Delete (Supprimer)
    • Dans le contexte de SQLite avec Flutter, le CRUD fait référence à l'ensemble des opérations de base qui peuvent être effectuées sur une base de données SQLite au sein d'une application Flutter.
    • Voici un bref aperçu de ces opérations :
      • Create: Ajouter de nouvelles données à la base de données. En SQL, cela est généralement réalisé avec la commande INSERT.
      • Read: Récupérer des données existantes de la base de données. Cela est fait avec la commande SELECT en SQL.
      • Update: Modifier des données existantes dans la base de données. En SQL, cela est fait avec la commande UPDATE.
      • Delete: Supprimer des données de la base de données. Cela est réalisé avec la commande DELETE en SQL.
    • Flutter est un framework populaire pour le développement d'applications mobiles, et SQLite est une bibliothèque de gestion de bases de données relationnelles légère.
    • Lorsqu'ils sont utilisés ensemble, ils permettent aux développeurs de créer des applications mobiles avec une gestion de données persistante et locale.
    • La bibliothèque sqflite est la plus populaire pour intégrer SQLite dans Flutter, facilitant ainsi la mise en œuvre d'opérations CRUD.
  2. Lecture (SELECT) :

    • Pour lire des données depuis la base de données, vous pouvez utiliser :.
      • Méthode 1: readDataWithCustomQuery(String sql) async
          Future<List<Map<String, dynamic>>> readDataWithCustomQuery(String sql) async {
            Database? mydb = await db;
            List<Map> response = await mydb!.rawQuery(sql);
            return response;
          }
        • Dans cette méthode, vous lui fournissez une requête SQL en tant que paramètre (sql), puis elle exécute cette requête à l'aide de la méthode rawQuery() de l'objet Database.
        • La méthode rawQuery() est utilisée pour exécuter des requêtes SQL brutes. Cela signifie que vous pouvez exécuter n'importe quelle requête SQL valide à l'intérieur de sql.
        • La méthode renvoie ensuite une liste de lignes sous forme de List<Map>, où chaque élément de la liste est un enregistrement représenté sous forme de map.
      • Méthode 2 : readDataFromTable() async
          Future<List<Map<String, dynamic>>> readData() async {
            final db = await openDatabase();
            return await db.query('my_table');
          }
        • Dans cette méthode, vous n'avez pas à fournir de requête SQL explicite. Au lieu de cela, vous ouvrez directement la base de données à l'aide de openDatabase() (vous devez avoir défini la table que vous souhaitez interroger au préalable).
        • Ensuite, vous utilisez la méthode query() de l'objet db pour exécuter une requête SELECT sur la table spécifiée (my_table).
        • Cette méthode renvoie également une liste de lignes sous forme de List<Map>, représentant les enregistrements dans la table.
    • Différences clés :
      • La première méthode vous permet de fournir une requête SQL personnalisée, ce qui signifie que vous avez un contrôle plus précis sur ce que vous interrogez dans la base de données.
      • La deuxième méthode est plus simple car elle ne nécessite pas de fournir de requête SQL. Cependant, elle est limitée à une opération SELECT sur la table préalablement définie.
      • Dans l'ensemble, le choix entre ces deux méthodes dépendra de vos besoins spécifiques. Si vous avez besoin de flexibilité pour exécuter des requêtes SQL complexes et personnalisées, la première méthode peut être plus appropriée. Si vous voulez une approche plus simple et préférable lorsque vous interrogez régulièrement une table spécifique, la deuxième méthode pourrait être plus adaptée.
  3. Insertion (INSERT) :

    • Pour insérer des données dans la base de données, utilisez la méthode insert.
      • Méthode 1 : Future<int> insertData(String name, int age) async
          Future<int> insertData(String name, int age) async {
            final db = await openDatabase();
            return await db.insert('my_table', {'name': name, 'age': age});
          }
        • Dans cette méthode, vous spécifiez les données à insérer en tant que paramètres (name et age). Vous utilisez ensuite la méthode insert() de l'objet db pour insérer ces données dans la table spécifiée (my_table).
        • Cette méthode renvoie un entier représentant l'ID de la ligne nouvellement insérée, ou -1 en cas d'erreur.
      • Méthode 2 : insertData(String sql) async
          Future<int> insertData(String sql) async {
            Database? mydb = await db ; 
            int  response = await  mydb!.rawInsert(sql);
            return response ; 
          }
        • Dans cette méthode, vous fournissez une requête SQL d'insertion en tant que paramètre (sql). Vous exécutez ensuite cette requête SQL à l'aide de la méthode rawInsert() de l'objet Database.
        • Cette méthode renvoie également un entier, mais il est important de noter que son comportement dépend de la requête SQL fournie. Si la requête SQL est une instruction d'insertion valide, elle renverra l'ID de la ligne nouvellement insérée.
        • Cependant, si la requête SQL est incorrecte ou mal formée, elle peut renvoyer -1 ou un autre code d'erreur.
      • Différences clés :
        • La première méthode (insertData(String name, int age)) est plus sûre car elle utilise des paramètres pour passer les données d'insertion, ce qui protège contre les attaques par injection SQL et garantit que les données sont correctement échappées.
        • La deuxième méthode (insertData(String sql)) nécessite de fournir une requête SQL brute en tant que paramètre, ce qui signifie que vous avez un contrôle complet sur la requête, mais vous devez être très prudent pour éviter les erreurs d'injection SQL.
        • En résumé, la première méthode est généralement recommandée car elle est plus sûre et plus simple à utiliser pour les opérations d'insertion de données courantes. La deuxième méthode peut être utile si vous avez besoin d'une flexibilité totale pour créer des requêtes SQL personnalisées, mais elle nécessite une gestion plus attentive des requêtes.
  4. Mise à jour (UPDATE) :

    • Pour mettre à jour des données existantes, utilisez la méthode update.
      • Méthode 1 : Future<int> insertData(String name, int age) async
          Future<int> updateData(int id, String name, int age) async {
            final db = await openDatabase();
            return await db.update(
              'my_table',
              {'name': name, 'age': age},
              where: 'id = ?',
              whereArgs: [id],
            );
          }
        • Dans cette méthode, vous spécifiez les données à mettre à jour en tant que paramètres (id, name, age). Vous utilisez ensuite la méthode update() de l'objet db pour mettre à jour les données dans la table spécifiée (my_table).
        • La méthode update() prend en charge des arguments spécifiques pour définir la clause WHERE (where et whereArgs) pour indiquer quelles lignes de la table doivent être mises à jour. Elle renvoie le nombre de lignes mises à jour.
      • Méthode 2 : updateData(String sql) async
          updateData(String sql) async {
            Database? mydb = await db ; 
            int response = await mydb!.rawUpdate(sql);
            return response ; 
          }
        • Dans cette méthode, vous fournissez une requête SQL d'update en tant que paramètre (sql). Vous exécutez ensuite cette requête SQL à l'aide de la méthode rawUpdate() de l'objet Database.
        • Cette méthode renvoie également un entier, mais il est important de noter que son comportement dépend de la requête SQL fournie. Si la requête SQL est une instruction d'update valide, elle renverra le nombre de lignes mises à jour.
        • Si la requête SQL est incorrecte ou mal formée, elle peut renvoyer -1 ou un autre code d'erreur.
    • Différences clés :
      • La première méthode (updateData(int id, String name, int age)) est plus sûre car elle utilise des paramètres pour passer les données de mise à jour, ce qui protège contre les attaques par injection SQL et garantit que les données sont correctement échappées.
      • La deuxième méthode (updateData(String sql)) nécessite de fournir une requête SQL brute en tant que paramètre, ce qui signifie que vous avez un contrôle complet sur la requête, mais vous devez être très prudent pour éviter les erreurs d'injection SQL.
      • En résumé, la première méthode est généralement recommandée car elle est plus sûre et plus simple à utiliser pour les opérations de mise à jour de données courantes. La deuxième méthode peut être utile si vous avez besoin d'une flexibilité totale pour créer des requêtes SQL personnalisées, mais elle nécessite une gestion plus attentive des requêtes.
  5. Suppression (DELETE) :

    • Pour supprimer des données, utilisez la méthode delete.
        Future<int> deleteData(int id) async {
          final db = await openDatabase();
          return await db.delete(
            'my_table',
            where: 'id = ?',
            whereArgs: [id],
          );
        }
    • En utilisant ces méthodes, vous pouvez gérer les opérations courantes sur une base de données SQLite dans votre application Flutter. Assurez-vous de gérer les erreurs correctement en utilisant des blocs try-catch pour garantir la stabilité de votre application.
  6. Applications

    • Tâche 1 : Création de la base de données SQLite
      • Objectif
        • Créer une base de données SQLite nommée "animaux" avec une table "type_animaux" dans une application Flutter à l'aide de Visual Studio Code.
      • Étapes :
        • Créez un nouveau projet Flutter dans Visual Studio Code.'tp_nimaux'
        • Ouvrez le fichier main.dart dans le répertoire lib de votre projet.
        • Supprimez tout le contenu par défaut du fichier main.dart.
        • Ajoutez le package sqflite à votre fichier pubspec.yaml pour utiliser SQLite.
            dependencies:
              path_provider: ^2.1.0 
              path: ^1.6.4 
              sqflite: ^2.3.0
        • En besoin utilisez les commandes suivantes flutter pub upgrade --major-versions et flutter pub outdated
        • Créez un fichier Dart séparé pour gérer la base de données. Vous pouvez nommer ce fichier "sqlDataBase.dart".
        • Importez les packages nécessaires dans votre fichier Dart.
            import 'package:sqflite/sqflite.dart';
            import 'package:path/path.dart';
        • Créez une fonction pour initialiser la base de données SQLite avec la table "type_animaux".
            // sqlDataBase.dart
            Future<Database> openDataBase() async {
              final databasePath = await getDatabasesPath();
              final path = join(databasePath, 'animaux.db');
              return openDatabase(path, version: 1, onCreate: (db, version) async {
                // Créez ici la structure de votre table "type_animaux".
                await db.execute('''
                  CREATE TABLE type_animaux (
                    id INTEGER PRIMARY KEY AUTOINCREMENT,
                    nom TEXT NOT NULL,
                    espece TEXT NOT NULL
                  )
                ''');
              });
            }
        • Créez un nouveau fichier Dart nommé "home.dart" dans le répertoire de votre projet Flutter.
        • Dans "home.dart", vous pouvez définir une classe HomeScreen pour cette partie de l'application.
            import 'package:flutter/material.dart';
            
            class HomeScreen extends StatefulWidget {
              @override
              _HomeScreenState createState() => _HomeScreenState();
            }
            
            class _HomeScreenState extends State {....................
          • La page que vous devez réaliser doive ressemble à l'image suivant:
          • Solution
            import 'package:flutter/material.dart';
            import 'sqlDataBase.dart';
            import 'liste_animaux.dart';
            void main() {
              runApp(MyApp());
            }
            
            class MyApp extends StatelessWidget {
              @override
              Widget build(BuildContext context) {
                return MaterialApp(
                  title: 'Mon App',
                  theme: ThemeData(
                    primarySwatch: Colors.blue,
                  ),
                  home: HomeScreen(),
                );
              }
            }
            
            class HomeScreen extends StatefulWidget {
              @override
              _HomeScreenState createState() => _HomeScreenState();
            }
            
            class _HomeScreenState extends State<HomeScreen> {
              TextEditingController nomController = TextEditingController();
              TextEditingController especeController = TextEditingController();
            
              @override
              Widget build(BuildContext context) {
                return Scaffold(
                  appBar: AppBar(
                    title: const Text('Ajouter un Animal'),
                  ),
                  body: Padding(
                    padding: const EdgeInsets.all(16.0),
                    child: Column(
                      mainAxisAlignment: MainAxisAlignment.start,
                      crossAxisAlignment: CrossAxisAlignment.center,
                      children: <Widget>[
                        TextField(
                          controller: nomController,
                          decoration: const InputDecoration(labelText: 'Nom de l\'animal'),
                        ),
                        TextField(
                          controller: especeController,
                          decoration: const InputDecoration(labelText: 'Espèce de l\'animal'),
                        ),
                        const SizedBox(height: 20.0),
                        ElevatedButton(
                          onPressed: () async {
                            final nom = nomController.text;
                            final espece = especeController.text;
            
                            if (nom.isNotEmpty && espece.isNotEmpty) {
                              final db = SqlDb();
                              final id = await db.insertTypeAnimal(nom, espece);
            
                              if (id != null) {
                                ScaffoldMessenger.of(context).showSnackBar(
                                  SnackBar(
                                    content: Text('Animal ajouté avec succès (ID: $id)'),
                                  ),
                                );
                                nomController.clear();
                                especeController.clear();
                              } else {
                                ScaffoldMessenger.of(context).showSnackBar(
                                  const SnackBar(
                                    content: Text('Erreur lors de l\'ajout de l\'animal.'),
                                  ),
                                );
                              }
                            } else {
                              ScaffoldMessenger.of(context).showSnackBar(
                                const SnackBar(
                                  content: Text('Veuillez remplir tous les champs.'),
                                ),
                              );
                            }
                          },
                          child: const Text('Ajouter un Animal'),
                        ),
                         const SizedBox(height: 20.0),
                         ElevatedButton(
                          onPressed: () {
                            Navigator.push(
                              context,
                              MaterialPageRoute(builder: (context) => const ListeAnimauxScreen()),
                            );
                          },
                          child: const Text('Voir la liste des animaux'),
                        )
            
                      ],
                    ),
                  ),
                );
              }
            }
            
        • Intégrez "HomeScreen" dans "main.dart"
        • Dans "main.dart", importez "home.dart" et utilisez la classe HomeScreen comme partie de votre application.
            import 'package:flutter/material.dart';
            import 'home.dart'; // Importez le fichier home.dart
            
            void main() async {
              WidgetsFlutterBinding.ensureInitialized();
              runApp(MyApp());
            }
            
            class MyApp extends StatelessWidget {
              @override
              Widget build(BuildContext context) {
                return MaterialApp(
                  title: 'Mon Application',
                  home: HomeScreen(), // Utilisez HomeScreen comme page d'accueil
                );
              }
            }
    • Tâche 2 : Insertion de données dans la base de données
      • Objectif : Insérer des données (nom et espèce/type d'animaux) dans la table "type_animaux" de la base de données SQLite créée précédemment.
      • Étapes :
        • Créez une classe TypeAnimal pour représenter les données.
            
            class TypeAnimal {
              final String nom;
              final String espece;
            
              TypeAnimal(this.nom, this.espece);
            }
        • Utilisez la première méthode d'insertion pour insérer des données dans la table "type_animaux".
            Future<int> insertTypeAnimal(String nom, String espece) async {
              final db = await openDatabase();
              return await db.insert('type_animaux', {'nom': nom, 'espece': espece});
            }
        • Utilisez la deuxième méthode d'insertion (SQL brut) pour insérer des données dans la table "type_animaux".
            Future<int> insertTypeAnimal(String sql) async {
              Database? mydb = await db; 
              int response = await mydb!.rawInsert(sql);
              return response;
            }
        • Dans votre application, créez un formulaire avec des champs de texte pour saisir le nom et l'espèce/type de l'animal à insérer.
        • Lorsque l'utilisateur soumet le formulaire, utilisez l'une des méthodes d'insertion pour ajouter le type d'animal à la table "type_animaux".
        • Affichez un message de confirmation pour indiquer que l'insertion a réussi.
    • Tâche 3 : Affichage des enregistrements dans un ListView
      • Objectif
        • Afficher les enregistrements de la table "type_animaux" dans un ListView en utilisant deux méthodes différentes.
      • Étapes :
        • Créez une liste pour stocker les enregistrements récupérés de la base de données.
            List typeAnimauxList = [];
          Ajoutez une fonction pour récupérer les enregistrements de la table "type_animaux" depuis la base de données.
            Future<List<TypeAnimal>> getTypeAnimaux() async {
              final db = await openDatabase();
              final List<Map<String, dynamic>> maps = await db.query('type_animaux');
              return List.generate(maps.length, (i) {
                return TypeAnimal(
                  maps[i]['nom'],
                  maps[i]['espece'],
                );
              });
            }
        • Utilisez la méthode getTypeAnimaux pour obtenir les enregistrements de la table "type_animaux" et les stocker dans la liste typeAnimauxList.
            typeAnimauxList = await getTypeAnimaux();
        • Créez un widget ListView.builder pour afficher la liste des enregistrements dans votre interface utilisateur.
            ListView.builder(
              itemCount: typeAnimauxList.length,
              itemBuilder: (context, index) {
                final typeAnimal = typeAnimauxList[index];
                return ListTile(
                  title: Text(typeAnimal.nom),
                  subtitle: Text(typeAnimal.espece),
                );
              },
            )
        • Vous pouvez maintenant afficher la liste des enregistrements dans votre application sous le formulaire d'insertion.
    • Tâche 4 : Ajouter les méthodes de modification et de suppression.
      • Votre application doit ressemble à l'image suivant:
  7. Fichiers sources