Les problèmes d’exactitude et de cohérence des données peuvent conduire à tout, des inconvénients mineurs aux problèmes majeurs de l’entreprise. Il est essentiel de construire un code qui stocke, modifie et efface en toute sécurité les données de votre base de données.
Entrez dans les transactions de base de données Laravel.
Les transactions de base de données sont une approche efficace pour garantir l’intégrité des données. Laravel simplifie ces transactions sur un large éventail de bases de données.
Mais que sont-elles exactement ? Comment les réaliser dans Laravel ?
À la fin de ce guide complet, vous aurez tout appris sur les transactions de base de données dans Laravel et comment les utiliser efficacement dans votre projet.
Que sont les transactions de base de données Laravel ?
Avant de nous lancer dans l’aspect technique des choses, comprenons d’abord ce que sont les transactions de base de données Laravel et comment vous pouvez en tirer parti.
Une transaction de base de données est un ensemble d’opérations que vous pouvez effectuer en toute sécurité dans la structure de la base de données de votre application, comme des requêtes SQL pour modifier des données (par exemple, des mises à jour, des suppressions et des insertions).
À tout moment, vous pouvez décider d’annuler toutes les requêtes de la transaction. En outre, toutes les requêtes que vous effectuez seront traitées comme une seule action par la base de données.
Voyons un exemple de ceci.
Supposons que nous ayons une application qui permet aux utilisateurs de créer des comptes. Naturellement, il peut y avoir un ou plusieurs utilisateurs affiliés à chaque compte. Si cette application génère simultanément un compte et le premier utilisateur, vous devrez gérer ce qui se passe si un compte est généré correctement, mais que l’utilisateur ne l’est pas.
Jetez un coup d’œil à cet exemple de code :
// Create Account
$newAcct = Account::create([
'accountname' => Input::get('accountname'),
]);
// Create User
$newUser = User::create([
'username' => Input::get('username'),
'account_id' => $newAcct->id,
]);
Il y a deux scénarios ici qui peuvent causer des problèmes désagréables :
- Le compte n’est pas généré
- Échec de la création d’un utilisateur
Considérons la dernière situation.
Le fait d’avoir un compte sans utilisateur disponible entraîne une incohérence des données dans la base de données. Pour résoudre ce problème, vous pouvez soit passer par la tâche décourageante de coder autour de ce problème, soit économiser beaucoup de code ou simplement l’envelopper dans une transaction pour faire les choses rapidement.
Si les transactions de base de données sont présentes dans la plupart des bases de données SQL, elles varient principalement dans leur mise en œuvre et leur efficacité. Les systèmes populaires tels que MySQL, SQLite, PostgreSQL et Oracle prennent en charge les transactions, vous ne devriez donc pas avoir de difficultés à déployer votre base de données SQL préférée.
Migrations
La migration est une fonctionnalité cruciale de Laravel qui vous permet de créer une table dans votre base de données, d’y apporter des modifications et de partager le schéma de base de données de l’application. Vous pouvez utiliser la migration Laravel pour modifier des tables en ajoutant de nouvelles colonnes ou en supprimant des colonnes existantes.
Supposons que vous discutez d’idées avec une équipe et que vous devez apporter des modifications à la table. Le fichier SQL doit être partagé et importé par un membre de l’équipe. Il est possible qu’il oublie d’importer le fichier SQL, ce qui entraîne des problèmes de fonctionnement de l’application.
C’est là que la migration Laravel vient à la rescousse. Vous pouvez ajouter une nouvelle colonne à votre base de données ou supprimer des entrées sans affecter celles qui sont déjà présentes.
Seeders
Le « seeding » est un outil fourni par Laravel aux développeurs pour faciliter le test de différents types de données, corriger les bogues et régler les performances. Vous pouvez ajouter automatiquement plusieurs lignes de données factices à votre table de base de données via le « seeder » de base de données en une seule commande.
Ainsi, vous pouvez recommencer avec une nouvelle base de données et des valeurs fictives au lieu de devoir les saisir manuellement à chaque fois que la base de données est restaurée.
Options pour les transactions de base de données Laravel
Laravel propose différents outils pour gérer vos données comme Adminer. Pour les transactions de base de données, il existe trois méthodes du côté de la base de données pour démarrer une transaction manuellement et avoir un contrôle total sur la gestion des transactions.
De nombreux utilisateurs trouvent ces options plus flexibles pour définir exactement quand une transaction doit être validée ou annulée :
- Créer une transaction : Utilisez la commande
DB::beginTransaction();
pour lancer une transaction. - Annuler une transaction : Utilisez la commande
DB::rollBack();
si vous souhaitez apporter des modifications ou annuler des actions. - Valider une transaction : Si tout s’est déroulé comme prévu, utilisez la commande
DB::commit();
.
N’oubliez jamais de conclure chaque transaction ouverte par une action de commit ou de rollback, en particulier les boucles. Sinon, cette méthode manuelle sera désynchronisée et vos enregistrements ne seront pas mis à jour.
Comment travailler avec votre base de données Laravel
Les migrations et les seeders, comme mentionné précédemment, sont des solutions sophistiquées conçues pour les développeurs Laravel afin de déployer, supprimer et restaurer rapidement la base de données d’une application en réduisant les disparités. C’est très pratique, surtout lorsque plusieurs développeurs travaillent sur la même application.
Cette section vous montrera comment utiliser facilement les migrations et les seeders avec votre base de données Laravel à l’aide des commandes artisanales.
Conditions préalables
Voici ce dont vous avez besoin pour commencer :
- Un utilisateur non root avec les droits sudo sur un ordinateur local ou un serveur de développement Ubuntu 18.04. C’est une bonne idée d’avoir un pare-feu actif si vous utilisez un serveur distant.
- LEMP installé sur votre machine. Vous pouvez choisir d’installer Docker et Docker Compose pour exécuter votre application si vous vous sentez plus à l’aise pour travailler avec eux.
Notre outil DevKinsta est alimenté par Docker et utilisé par plus de 60,000+ développeurs et concepteurs pour créer et développer facilement des sites WordPress uniques ou multiples.
Il existe d’autres outils de développement web que vous pouvez utiliser en fonction de vos compétences et de vos besoins en matière de codage.
Migrations Laravel
Il existe deux méthodes dans une classe de migration : up et down. La méthode up est utilisée pour créer de nouvelles tables, index ou colonnes dans votre base de données. La méthode down doit annuler les effets de la méthode up.
Vous pouvez utiliser le constructeur de schémas de Laravel pour construire et modifier librement les tables dans chacune de ces méthodes. Par exemple, cette migration génère une table de vols :
use IlluminateDatabaseMigrationsMigration;
use IlluminateDatabaseSchemaBlueprint;
use IlluminateSupportFacadesSchema;
class CreateFlightsTable extends Migration {
/**
* Run the migrations.
*
* @return void
*/
public function up() {
Schema::create('flights', function (Blueprint $table) {
$table->bigIncrements('id');
$table->string('name');
$table->string('airline');
$table->timestamps();
});
}
/**
* Reverse the migrations.
*
* @return void
*/
public function down() {
Schema::drop('flights');
}
N’oubliez pas que les commandes make:migration
doivent préciser le nom de la table. Assurez-vous donc que le table_name
correspond à ce que vous voulez.
Vous pouvez utiliser les options --table
et --create
pour spécifier le nom de la table et si la migration créera une nouvelle table comme indiqué ci-dessous :
php artisan make:migration create_users_table --create=users
php artisan make:migration add_votes_to_users_table --table=users
Votre répertoire database/migrations comprendra désormais la nouvelle migration. Chaque nom de fichier de migration comprend un horodatage, que Laravel utilise pour déterminer l’ordre de migration.
Vous avez également la possibilité de définir un --path
, qui doit être lié au répertoire racine de votre installation. Utilisez la commande suivante :
php artisan migrate:make foo --path=app/migrations
Exécution des migrations
Il existe quelques commandes utiles dont vous pouvez tirer parti lorsque vous exécutez des migrations. Passons en revue quelques-unes d’entre elles :
php artisan migrate
: Cette commande publie l’ensemble de votre schéma dans la base de données. Elle génère également une table dans la base de données.php artisan migrate --path=app/foo/migrations
: Cette commande exécute toutes les migrations sous un répertoire. Si vous recevez un message d’erreur « Nothing to migrate », exécutez la commandephp artisan migrate --path=database/migrations/foo
sans le répertoire app.php artisan migrate --package=vendor/package
: Utilisez cette commande si vous voulez exécuter des migrations pour un paquet.
Il arrive parfois que vous obteniez une erreur « Class not found » lors de l’exécution des migrations. Si c’est le cas, exécutez la commande composer dump-autoload
.
Certaines migrations peuvent être dangereuses et entraîner la perte de vos données. Par conséquent, Laravel vous demandera de confirmer l’exécution des commandes afin de sauvegarder vos données.
Si vous ne souhaitez pas être invité, utilisez --force flag
pour forcer les commandes comme suit :
php artisan migrate --force
Retour en arrière des migrations
Utilisez la commande rollback lorsque vous devez annuler le dernier lot de migration comme ci-dessous :
php artisan migrate:rollback
Voici quelques autres commandes de rollback que vous pouvez utiliser :
php artisan migrate:reset
: Cette commande annule toutes les migrations, pas seulement la dernière opération.php artisan migrate:fresh
: Utilisez cette commande lorsque vous souhaitez une nouvelle installation de votre base de données. Elle supprime toutes les tables existantes et exécute la commandemigration
.php artisan migrate:refresh
: Cette commande est une commande deux en un qui exécute les deux commandes:rollback and migrate
.php artisan migrate:fresh --seed
: Elle exécute la commandemigrate:fresh
avant d’ensemencer la base de données. Lorsque vous installez l’application sur un nouvel hôte, vous pouvez utiliser cette commande pour ensemencer (c’est-à-dire téléverser des données dans) la base de données.
Laravel Seeding
Un seeder est une classe qui crée et place des échantillons de données (seeds) dans une base de données. Laravel fournit une technique simple pour ensemencer votre base de données avec des données de test en utilisant des classes seed dans le répertoire database/seeds.
Vous êtes libre de choisir le nom de vos classes seed. Mais nous vous conseillons de suivre un modèle de dénomination clair de votre choix, comme UsersTableSeeder. Ensuite, une classe DatabaseSeeder
est créée pour vous par défaut.
Voici un exemple de classe de seed de base de données dans Laravel :
class DatabaseSeeder extends Seeder {
public function run() {
$this->call('UserTableSeeder');
$this->command->info('User table seeded!');
}
}
class UserTableSeeder extends Seeder {
public function run() {
DB::table('users')->delete();
User::create(array('email' => '[email protected]'));
}
}
Création d’un seeder
Générer des seeders est très facile. Vous pourriez le faire les yeux fermés (mais ne le faites pas).
Exécutez la commande make:seeder
artisan pour créer un seeder. Maintenant, le répertoire database/seeds comprendra tous les seeders produits par le framework :
php artisan make:seeder UsersTableSeeder
La méthode par défaut d’une classe de seeder est exécutée. Le processus a lieu lorsque vous appliquez la commande artisanale db:seed
. Vous pouvez placer des données dans votre base de données de la manière que vous préférez en utilisant la fonction run. En outre, il vous est tout à fait possible d’utiliser les usines de modèles Eloquent ou Query Builder pour insérer des données manuellement.
Quoi qu’il en soit, vous devez garder à l’esprit que pendant l’ensemencement de la base de données, la protection contre l’affectation en masse est automatiquement désactivée.
Ici, nous allons apporter des modifications à la classe de base DatabaseSeeder
et ajouter une instruction d’insertion de base de données à la méthode d’exécution :
<?php
use IlluminateDatabaseSeeder;
use IlluminateSupportFacadesDB;
use IlluminateSupportFacadesHash;
use IlluminateSupportStr;
class DatabaseSeeder extends Seeder {
/**
* Run the database seeds.
*
* @return void
*/
public function run() {
DB::table('users')->insert([
'name' => Str::random(10),
'email' => Str::random(10).'@gmail.com',
'password' => Hash::make('password'),
]);
}
}
Si vous souhaitez indiquer des dépendances dans le code de la méthode d’exécution, le conteneur de service Laravel les résoudra automatiquement.
En outre, vous pouvez utiliser la fonction call
pour exécuter différentes classes d’ensemencement à partir de cette classe, ce qui vous permet de personnaliser l’ordre d’ensemencement. Vous pouvez répartir l’ensemencement de votre base de données sur différents fichiers, en veillant à ce qu’aucune classe d’ensemencement ne s’étende excessivement.
Saisissez le nom de la classe de semis que vous souhaitez utiliser comme indiqué ci-dessous :
/**
* Run the database seeds.
*
* @return void
*/
public function run() {
$this->call([
UsersTableSeeder::class,
PostsTableSeeder::class,
CommentsTableSeeder::class,
]);
}
Exécution des seeders
Après avoir généré votre seeder, vous devrez peut-être utiliser la commande dump-autoload
pour recréer l’auto-chargeur de Composer :
composer dump-autoload
Ensuite, vous devez exécuter la commande db:seed
artisan pour ensemencer votre base de données :
php artisan db:seed
Cette commande exécute la classe DatabaseSeeder
par procuration, qui peut être utilisée pour exécuter d’autres classes d’ensemencement. Vous pouvez toutefois utiliser le paramètre --class
pour exécuter séparément une classe de seeding particulière, comme suit :
php artisan db:seed --class=UserTableSeeder
Que se passe-t-il si vous souhaitez recréer votre base de données à partir de zéro, y compris supprimer toutes les tables et exécuter à nouveau toutes vos migrations ? Dans ce cas, utilisez la commande migrate:fresh
pour ensemencer votre base de données.
php artisan migrate:fresh --seed
Comme c’est le cas avec les migrations, certains processus de seeding peuvent entraîner une perte de données ou des modifications indésirables. Pour cette raison, vous serez invité à donner votre accord avant l’exécution des seeders afin de vous protéger de l’exécution de commandes d’ensemencement sur votre base de données primaire.
Si vous êtes suffisamment confiant et que vous ne voulez pas être interrompu par cette étape de sécurité, utilisez le drapeau --force
ci-dessous :
php artisan db:seed --force
5 autres façons d’utiliser les requêtes de base de données brutes dans Laravel
Bien que Laravel fournisse des outils pratiques tels qu’Eloquent et Query Builder, vous pouvez toujours effectuer des requêtes brutes en utilisant SQL. Nous avons rassemblé cinq façons différentes de le faire.
Mais avant de commencer, vous devez savoir que les requêtes brutes ne sont pas sécurisées automatiquement, ce qui en fait une approche risquée. Par conséquent, si vous donnez des paramètres à la requête, assurez-vous qu’ils sont au bon format et ont les bonnes valeurs, comme un nombre plutôt qu’un texte.
Calculs de moyenne, de somme et de nombre
Vous pouvez utiliser une requête brute si vous souhaitez créer GROUP BY ()
, puis utiliser les fonctions d’agrégation MySQL telles que Count()
, SUM()
, AVG()
, MIN()
ou MAX()
comme le montre l’exemple suivant :
$users = DB::table('users')
->selectRaw('count(*) as user_count, status')
->where('status', '<>', 1)
->groupBy('status')
->get();
Il est même possible de faire à la fois count()
et avg()
dans la même requête SQL :
$salaries = DB::table('salaries')
->selectRaw('companies.name as company_name, avg(salary) as avg_salary, count(*) as people_count')
->join('companies', 'salaries.company_id', '=', 'companies.id')
->groupBy('companies.id')
->orderByDesc('avg_salary')
->get();
Filtrage des années
Si vous devez effectuer des calculs SQL dans GROUP BY
ou ORDER BY
, vous pouvez utiliser les requêtes groupByRaw()
et orderByRaw()
. Après le regroupement, vous pouvez également utiliser l’instruction where
en utilisant une requête SQL having
avec havingRaw ()
.
Par exemple, la commande ci-dessous montre comment regrouper un champ date/heure par année :
$results = User::selectRaw('YEAR(birth_date) as year, COUNT(id) as amount')
->groupByRaw('YEAR(birth_date)')
->havingRaw('YEAR(birth_date) > 2000')
->orderByRaw('YEAR(birth_date)')
->get();
Calcul d’un seul champ (sous-requête)
Supposons que vous vouliez calculer une colonne à partir d’une autre et renvoyer le résultat dans une requête SQL. Comment pouvez-vous y parvenir ?
Jetons un coup d’oeil :
$products = Product::select('id', 'name')
->selectRaw('price - discount_price AS discount')
->get();
Voici un autre exemple d’une déclaration SQL CASE
:
$users = DB::table('users')
->select('name', 'surname')
->selectRaw("(CASE WHEN (gender = 1) THEN 'M' ELSE 'F' END) as gender_text")
->get();
Convertir un ancien SQL
Il est fréquent d’avoir une instruction SQL qui nécessite une conversion vers Eloquent ou Query Builder, notamment à partir d’un ancien projet sur lequel vous avez travaillé.
Vous n’avez pas vraiment besoin de faire cela. Au lieu de cela, vous pouvez simplement utiliser l’instruction DB::select()
comme indiqué :
$results = DB::select('select * from users where id=?', [1]);
Exécuter une requête sans résultats
DB::statement
peut exécuter une requête SQL, sans obtenir de résultats comme INSERT
ou UPDATE
sans variables.
Cette fonction est fréquemment utilisée lors de la migration de bases de données, lorsqu’une structure de table change et que les anciennes données doivent être remplacées par les nouvelles :
DB::statement('UPDATE users SET role_id = 1 WHERE role_id IS NULL AND YEAR(created_at) > 2020');
En outre, DB::statement()
peut exécuter toute requête SQL avec un schéma qui n’est pas limité à des valeurs ou des colonnes. Voici un exemple :
DB::statement('DROP TABLE users');
DB::statement('ALTER TABLE projects AUTO_INCREMENT=123');
Résumé
À présent, vous devriez avoir une compréhension approfondie des transactions de base de données dans Laravel et de la façon de les mettre en œuvre. Non seulement elles contribuent à l’intégrité des données, mais elles permettent également d’optimiser les performances de Laravel et de faciliter votre processus de développement.