IdentifiantMot de passe
Loading...
Mot de passe oublié ?Je m'inscris ! (gratuit)
Navigation

Inscrivez-vous gratuitement
pour pouvoir participer, suivre les réponses en temps réel, voter pour les messages, poser vos propres questions et recevoir la newsletter

Laravel PHP Discussion :

Update de plusieurs enregistrements avec des valeurs différentes en une requête unique


Sujet :

Laravel PHP

  1. #1
    Membre à l'essai
    Profil pro
    Développeur Web
    Inscrit en
    Décembre 2006
    Messages
    27
    Détails du profil
    Informations personnelles :
    Localisation : France

    Informations professionnelles :
    Activité : Développeur Web

    Informations forums :
    Inscription : Décembre 2006
    Messages : 27
    Points : 20
    Points
    20
    Par défaut Update de plusieurs enregistrements avec des valeurs différentes en une requête unique
    Bonjour,

    Je cherchais comment, dans Laravel, faire la mise à jour de plusieurs enregistrements avec des valeurs différentes.
    Je suis parvenu à mes fins mais quelle lutte ! J'ai trouvé la démarche assez tordue ; ça m'a pris quelques heures pour y arriver.

    N'ayant qu'une petite année d'expérience sur ce framework, je souhaitais savoir s'il y avait une manière plus simple de m'y prendre.

    Ma table "trainings" se présente comme suit :

    id user_id category_id title order
    1 1 1 Maupassant 1
    2 1 1 Hugo 2
    3 1 1 Voltaire 3

    ... et l'idée, c'était, qu'au moment où je supprime un élément, de retirer une unité à chaque ordre des éléments qui avaient un ordre supérieur à celui de l'élément supprimé. Aussi, dans le cas où j'ai 10000 enregistrements, je me voyais mal balancer 9999 requêtes (en supprimant le premier par exemple).

    Du coup j'ai procédé comme suit :

    Méthode de suppression de mon contrôleur "TrainingController"

    Code php : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
    13
    14
    15
    16
    17
    18
    19
    20
    21
    22
    23
    24
    25
    26
    27
    28
    29
    30
    31
    32
    33
     
        public function destroy(Training $training)
        {
            if (Auth::user()->can('delete', $training)) {
                $id = $training->id;
     
                $trainings = Training::where([
                    ['category_id', '=', $training->category_id],
                    ['order', '>', $training->order]
                ])->get(['id', 'user_id', 'title', 'order']);
     
                foreach ($trainings as $item) {
                    $item->order = $item->order - 1;
                }
     
                $refs = $trainings->pluck('order', 'pluck')->toArray();
                $newRefs = [];
     
                foreach ($refs as $key => $ref) {
                    array_push($newRefs, "($key,$ref)");
                }
     
                $training->delete();
     
                $query = 'INSERT INTO trainings (`id`,`user_id`,`title`,`order`) VALUES ' . implode(',', $newRefs) . ' ON DUPLICATE KEY UPDATE `user_id`=VALUES(`user_id`),`title`=VALUES(`title`),`order`=VALUES(`order`)';
                $stmt = DB::getPdo()->prepare($query);
                $stmt->execute();
     
                return response()->json("Training $id deleted", 200);
            }
     
            return response()->json("Unauthorized action for this user", 401);
        }

    ... sachant que j'ai dû créer un accesseur dans mon modèle pour obtenir la valeur 'pluck' :

    Accesseur de mon modèle "Training"

    Code php : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
    5
     
        public function getPluckAttribute()
        {
            return $this->id . "," . $this->user_id . ",'" . $this->title . "'";
        }

    Comme vous pouvez le voir, je suis passé par PDO car je n'ai pas trouvé comment m'y prendre avec Eloquent.
    Quant à l'accesseur, c'est parce que la méthode pluck ne semble accepter que deux arguments max, ce que je trouve assez bizarre vu que ça peut arriver souvent de chercher à récupérer plus de deux colonnes, non ?

    Bref, je suis heureux d'être arrivé au résultat escompté, non sans acharnement, mais...

    M'y suis-je pris comme il faut et n'y-a-t-il pas moyen de faire plus simple ?

    Au plaisir de vous lire.

  2. #2
    Membre habitué
    Homme Profil pro
    Développeur BackEnd - FrontEnd
    Inscrit en
    Avril 2015
    Messages
    90
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Âge : 42
    Localisation : France, Essonne (Île de France)

    Informations professionnelles :
    Activité : Développeur BackEnd - FrontEnd
    Secteur : Services de proximité

    Informations forums :
    Inscription : Avril 2015
    Messages : 90
    Points : 136
    Points
    136
    Par défaut
    Avec laravel tu peux créer des requetes personnalisées en SQL brut via RAW SQL.

    Voir ici pour des explications : https://laravel.com/docs/master/data...unning-queries

  3. #3
    Membre à l'essai
    Profil pro
    Développeur Web
    Inscrit en
    Décembre 2006
    Messages
    27
    Détails du profil
    Informations personnelles :
    Localisation : France

    Informations professionnelles :
    Activité : Développeur Web

    Informations forums :
    Inscription : Décembre 2006
    Messages : 27
    Points : 20
    Points
    20
    Par défaut
    oui, j'avais vu cette page de la documentation mais ça ne permettait visiblement pas de répondre à mes besoins.

    DB::update peut mettre à jour plusieurs lignes mais toutes avec la même valeur, ce pourquoi j'en suis arrivé, au final, à cette requête "INSERT INTO ... ON DUPLICATE KEY UPDATE".
    Pour la faire, je n'ai pas vu "Raw SQL query" adaptée et c'est la raison pour laquelle je suis passé par PDO.

  4. #4
    Modérateur
    Avatar de grunk
    Homme Profil pro
    Lead dév - Architecte
    Inscrit en
    Août 2003
    Messages
    6 691
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Âge : 39
    Localisation : France, Côte d'Or (Bourgogne)

    Informations professionnelles :
    Activité : Lead dév - Architecte
    Secteur : Industrie

    Informations forums :
    Inscription : Août 2003
    Messages : 6 691
    Points : 20 222
    Points
    20 222
    Par défaut
    Simplement un truc comme ca aurait pas suffit ?

    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    DB::update('update trainings set order = order -1 where order > ?', [$training->order]);
    Pry Framework php5 | N'oubliez pas de consulter les FAQ Java et les cours et tutoriels Java

  5. #5
    Membre à l'essai
    Profil pro
    Développeur Web
    Inscrit en
    Décembre 2006
    Messages
    27
    Détails du profil
    Informations personnelles :
    Localisation : France

    Informations professionnelles :
    Activité : Développeur Web

    Informations forums :
    Inscription : Décembre 2006
    Messages : 27
    Points : 20
    Points
    20
    Par défaut
    Ah mais oui !

    J'obtiens bien ce que je souhaite ainsi :
    Code php : Sélectionner tout - Visualiser dans une fenêtre à part
    DB::update('UPDATE trainings SET `order` = `order` - 1 WHERE `category_id` = ' . $training->category_id . ' AND `order` > ?', [$training->order]);

    C'était tout simple en fait, sauf qu'étant un peu réfractaire au SQL, ça ne m'est pas venu à l'esprit.

    Merci grunk.

+ Répondre à la discussion
Cette discussion est résolue.

Discussions similaires

  1. Réponses: 8
    Dernier message: 09/06/2015, 14h01
  2. Réponses: 4
    Dernier message: 16/01/2010, 19h33
  3. Réponses: 6
    Dernier message: 31/07/2007, 16h15
  4. Concaténer plusieurs champs avec des valeurs uniques
    Par stefposs dans le forum VBA Access
    Réponses: 10
    Dernier message: 30/05/2007, 17h42
  5. Changer plusieur style avec des IDs différents?
    Par YanK dans le forum Général JavaScript
    Réponses: 2
    Dernier message: 02/07/2005, 14h33

Partager

Partager
  • Envoyer la discussion sur Viadeo
  • Envoyer la discussion sur Twitter
  • Envoyer la discussion sur Google
  • Envoyer la discussion sur Facebook
  • Envoyer la discussion sur Digg
  • Envoyer la discussion sur Delicious
  • Envoyer la discussion sur MySpace
  • Envoyer la discussion sur Yahoo