3
votes

Quelle est la meilleure façon de copier des données d'un champ à un autre lors de la création d'une migration d'un nouveau champ?

J'ai une table de base de données ayant un champ qui a un type de champ booléen. Maintenant, conformément à la nouvelle exigence, le champ doit être changé pour le type petit entier.

Pour y parvenir, j'ai créé une migration et ajouté le script dans le même fichier de migration pour copier la valeur de l'ancien champ vers le nouveau champ. Cependant, je pense que ce n’est pas la meilleure approche que j’ai suivie. Quelqu'un peut-il s'il vous plaît aider et conseiller sur la meilleure façon de gérer ce scénario.

public function up()
{
    Schema::table('skills', function (Blueprint $table) {
        $table->tinyInteger('skill_type_id')->nullable()->comment = '1 for advisory skills, 2 for tools, 3 for language & framework';
    });
    $skill_object = (new \App\Model\Skill());
    $skills = $skill_object->get();
    if (_count($skills)) {
        foreach($skills as $skill) {
            $skill_type  = 1;
            if ($skill->is_tool) {
                $skill_type = 2;
            }
            $skill_object->whereId($skill->id)->update(['skill_type_id' => $skill_type]);
        }
    }
}


0 commentaires

4 Réponses :


1
votes

Vous pouvez le faire avec 02 migrations, la première est de créer le nouveau champ, comme déjà fait. La seconde consiste à créer une migration avec instruction brute pour copier la valeur de l'ancien champ vers le nouveau champ. Si vous n'avez plus besoin de l'ancien champ, vous pouvez créer une troisième migration en supprimant l'ancien champ.

public function up()
{
    Schema::table('skills', function (Blueprint $table) {
       DB::statement('UPDATE skills SET skill_type_id = IF(is_tool, 2, 1)');
    }
}


2 commentaires

quel est l'avantage de créer 3 migrations? Je recherche la meilleure approche pour gérer ce scénario.


Avec 03 migrations, vous garantissez l'ordre d'exécution, gardez les intentions de migration propres et vous serez facilement restauré au cas où vous en auriez besoin.



2
votes

Vous pouvez le faire (mettre à jour les données) de la manière suivante dans votre scénario.

  • Créez des itinéraires séparés et mettez à jour les données après les migrations.
  • Créer un semeur (avec la même requête que ci-dessus dans le fichier de migrations) exécutez le semeur.

Mais les deux solutions ci-dessus sont peu risquées si vous essayez de faire cela avec votre base de données de production. Si quelqu'un accède par erreur à l'URL et exécute le semeur plusieurs fois, c'est difficile à gérer.

Je pense que le meilleur moyen de résoudre votre problème en amorçant (en modifiant) les données sur le même fichier de migration après avoir modifié le schéma, car les migrations ne seront plus exécutées (même par erreur), une fois qu'elles ont migré. Vous faites la bonne manière comme je le crois.


0 commentaires

1
votes

Vous êtes libre de développer votre propre manière d'accomplir cette tâche, mais en ce qui concerne les migrations, celles-ci sont destinées à contrôler et à partager le schéma de base de données de l'application au sein de l'équipe, pas les données réelles ;)

  • Vous pouvez créer un semeur distinct pour cette tâche.
  • Cela gardera votre migration propre et facile à restaurer si nécessaire.

REMARQUE: n'incluez pas cette classe de semeur dans DatabaseSeeder .

Ce type de classe de semoir est uniquement destiné à mettre à jour les données existantes après avoir corrigé la fonctionnalité actuelle (je prends en compte que vous avez déjà corrigé le code selon votre nouvelle exigence). Donc, il n'y a pas besoin de s'inquiéter de réexécuter la même classe de semeur.


0 commentaires

1
votes

Considérant ( laracast , stack-overflow ), je préférerai passer par votre chemin sur les suggestions fournies ci-dessus car je n'ai pas à maintenir une route supplémentaire ni une migration supplémentaire (03).

La seule amélioration que je peux suggérer ici, c'est vous peut utiliser une transaction de base de données comme ceci:

// create new column
DB::transaction(function () {
  update new column
  delete old column
});


0 commentaires