Noyade dans tableau associatifs et PDO

Ce sujet est résolu
Default
,

Bonjour,

J'essaye d'espérément de comprendre comment je pourrais insérer dans ma base de donnée un tableau en php. Voici le tableau en question :

    Array
(
    [CodeProduitImprime] => Array
        (
            [28] => 15
            [37] => 16
            [38] => 17
        )

    [Prix] => Array
        (
            [28] => 10
            [37] => 15
            [38] => 20
        )

    [Qte] => Array
        (
            [28] => 1
            [37] => 1
            [38] => 1
        )

    [FraisDePort] => Array
        (
            [1015] => 0
        )

    [Devise] => Array
        (
            [1015] => EUR
        )

    [Total] => Array
        (
            [1015] => 124.00
        )

)

Je parcours mon tableau comme ceci

    foreach($_POST as $NomDuChamps => $ValeurDuChamps)
{
    echo $NomDuChamps.':<br>';
        // Lecture de chaque tableau de chaque ligne
    foreach($ValeurDuChamps as $Id => $Valeur){
                // Affichage
        echo $Id.': '.$Valeur.'<br>';
    }
}

j'obtiens donc

Nom input: CodeProduitImprime:
Id 28: Valeur : 15
Id 37: Valeur : 16
Id 38: Valeur : 17
Nom input: Prix:
Id 28: Valeur : 10
Id 37: Valeur : 15
Id 38: Valeur : 20
Nom input: Qte:
Id 28: Valeur : 1
Id 37: Valeur : 1
Id 38: Valeur : 1
Nom input: FraisDePort:
Id 1015: Valeur : 0
Nom input: Devise:
Id 1015: Valeur : EUR
Nom input: Total:
Id 1015: Valeur : 124.00

Mais la c'est le néant ! Je suis incapable de faire un update en PDO en utilisant ce tableau. Je ne sais pas par quel bout le prendre et je suis totalement perdu.

Exemple, pour la première ligne, Je veux faire un update du champs CodeProduitImprime en modifiant 15 sur l'id 28 :-(
en gros UPDATE matable SET CodeProduitImprime = '15' WHERE id = '28'
et ainsi de suite en bouclant...

Je bloque depuis des heures alors je me permet de solliciter un conseil svp

Merci beaucoup!

11 Réponse

17162
,

Bonjour.
Tu devrais penser à reformater ton tableau de manière à éviter de devoir faire plusieurs requêtes SQL pour un même enregistrement.
Par exemple :

// Tableau d'origine :
$tab = [
    'CodeProduitImprime' => [28 => 15, 37 => 16, 38 => 17],
    'Prix' => [28 => 10, 37 => 15, 38 => 20],
    'Qte' => [28 => 1, 37 => 1, 38 => 1],
    'FraisDePort' => [1015 => 0],
    'Devise' => [1015 => 'EUR'],
    'Total' => [1015 => 124.00]
];
// Reformatage du tableau :
$records = [];
foreach ($tab as $field => $record)
{
    foreach ($record as $id => $value)
    {
        $records[$id][$field] = $value;
    }
}
// Ensuite tu peux formater tes requêtes SQL :
$updates = [];
foreach ($records as $id => $record)
{
    $update = 'UPDATE maTable SET ';
    $keysValues = [];
    foreach ($record as $field => $value)
    {
        if (is_string($value)) {
            $value = "'$value'";
        } elseif (is_float($value)) {
            $value = number_format($value, 2);
        }
        $keysValues[] = "$field = $value";
    }
    $update .= implode(', ', $keysValues);
    $update .= " WHERE id = $id";
    $updates[] = $update;
}

Il ne te reste plus que par la suite à faire tes requêtes SQL via une boucle, tu peux voir les résultats de la boucle pour les requêtes SQL et du code ci-dessus ici.
Si les données postées viennent d'un utilisateur, il serait préférable d'utiliser les méthodes prepare et execute de PDO pour éviter les injections en base de données.
Une info au passage, si les données concernant les valeurs numériques sont typées comme tel en base de données et non de type string, évites d'entourer leurs valeur par des quotes, car tu risques d'avoir des problèmes pour les updates si c'est le cas.

Default
,

Merci infiniement Lartak ! Je n'y serais jamais parvenu de cette manière :-)

Suite à un peu de repos, j'ai tout de même réussi ce que je voulais faire mais ma méthode est beaucoup plus lourde que la vôtre.

En effet, une partie des données doit être insérées dans une autre table de la base, je m'apperçois que je ne l'ai pas évoqué dans mon premier post. Les données à partir du champs "FraisDePort" sont destinées à une deuxième table.

Pourrais-je abuser de votre compétence pour m'aiguiller afin d'adapter votre code à cette possibilité s'il vous plaît ? Je n'y parviens pour le moment pas mais je continue d'essayer :-)

Encore merci !!

17162
,

Pourrais-je abuser de votre compétence pour m'aiguiller afin d'adapter votre code à cette possibilité s'il vous plaît ?

Pas de soucis.
Sans changer grand chose :

$tab = [
    'CodeProduitImprime' => [28 => 15, 37 => 16, 38 => 17],
    'Prix' => [28 => 10, 37 => 15, 38 => 20],
    'Qte' => [28 => 1, 37 => 1, 38 => 1],
    'FraisDePort' => [1015 => 0],
    'Devise' => [1015 => 'EUR'],
    'Total' => [1015 => 124.00]
];
// Reformatage du tableau :
$tables = [];
$firstTable = 'firstTable';
$secondTable = 'secondTable';
foreach ($tab as $field => $rec)
{
    foreach ($rec as $id => $value)
    {
        $table = $field === 'FraisDePort' ? $secondTable : $firstTable;
        $tables[$table][$id][$field] = $value;
    }
}
// Ensuite tu peux formater tes requêtes SQL :
$updates = [];
foreach ($tables as $table => $records)
{
    foreach ($records as $id => $record)
    {
        $update = "UPDATE $table SET ";
        $keysValues = [];
        foreach ($record as $field => $value)
        {
            if (is_string($value)) {
                $value = "'$value'";
            } elseif(is_float($value)) {
                $value = number_format($value, 2);
            }
            $keysValues[] = "$field = $value";
        }
        $update .= implode(', ', $keysValues);
        $update .= " WHERE id = $id";
        $updates[] = $update;
    }
}

Pour l'explication, j'ai simplement préfixé les enregistrements par le nom de la table lors du reformatage du tableau d'origine puis ajouté une boucle dans la générations des requêtes SQL.
Tu peux voir les résultats ici.
Il te suffit de modifier les valeurs des variables firstTable et secondTable par leurs valeurs réelles.

Default
,

Vous êtes formidable, merci beaucoup !! J'étais parti dans la direction de array_slice ....... J'ai cependant un petit soucis puisque j'ai plusieurs champs qui vont dans secondTable pas juste FraisDePort.

Lorsque je modifie :

$table = $field === 'FraisDePort' ? $secondTable : $firstTable;
//ajoutant cette ligne
$table = $field === 'Incfdp' ? $secondTable : $firstTable;

FraisDePort passe dans firstTable et Incfdp dans secondTable. Lorsque je retire la ligne, c'est l'inverse.

J'abuse donc encore un peu de votre gentillesse mais sincèrement, vu les heures (et nuits) que je viens d'y passer c'est une délivrance totale grâce à vous !!

17162
,

J'ai cependant un petit soucis puisque j'ai plusieurs champs qui vont dans secondTable pas juste FraisDePort.

Il te suffit de remplacer :

$table = $field === 'FraisDePort' ? $secondTable : $firstTable;

Par :

$table = in_array($field, ['FraisDePort']) ? $secondTable : $firstTable;

Dans le tableau dans lequel figure FraisDePort, tu y liste les champs qui sont propre à la seconde table.
Par contre, s'il y a beaucoup de champs pour le tableau, je te recommande de créer une variable en amont, d'y lister les champs concernés en tableau et renseigner la variable à la place du tableau dans la condition, soit :

$table = in_array($field, $taVariable) ? $secondTable : $firstTable;
Default
,

Je "code" pour mon loisir perso mais c'est beau de voir une telle maîtrise !

Donc je fais comme vous le dites

$taVariable  = array(['FraisDePort'], ['Incfdp']);
$table = in_array($field, $taVariable) ? $secondTable : $firstTable;

Et j'obtiens un résultat mais tout est dans firstTable :-(

// résultat
$pdo->query("UPDATE firstTable SET CodeProduitImprime = 'test2', Prix = '8.00', Qte = '2' WHERE id = 28");

$pdo->query("UPDATE firstTable SET CodeProduitImprime = 'test1', Prix = '7.00', Qte = '2' WHERE id = 39");

$pdo->query("UPDATE firstTable SET FraisDePort = '0', Incfdp = '0' WHERE id = 1015");

Encore merci, c'est vraiment très sympa !

EDIT : Oups, j'ai trouvé mon erreur :

$taVariable  = array('FraisDePort', 'Incfdp');

La ça fonctionne !

Merci beaucoup, je suis admiratif et vous remercie encore sincèrement pour votre temps ! Bonne journée à vous :-)

17162
,

De rien.
En effet tu avais mélangé les deux types de array:

  • Ce que j'appelle l'ancienne syntaxe : array()
  • La short array syntax : [].

Personnellement je préfère utiliser la seconde.

Default
,

Inutile de vous dire que je vais désormais utiliser votre methode lol :

$taVariable  = ['FraisDePort', 'Incfdp'];

Merci :-)

Default
,

Oups j'oubliais, la clause where diffère dans les deux tables:

  • sur la table 1 c'est where id = ..
  • sur la table 2 where idcommande = ...

Voyez-vous un moyen de résoudre cela ? J'abuse un peu ........

17162
,

Tu peux faire comme pour la table, juste avant la génération de la requête SQL, tu peux te baser sur le nom de la table et faire quelque chose comme :

// ...
$primaryKey = $table === $firstTable ? 'id' : 'idcommande';
$update = "UPDATE $table SET ";
// etc ...
$update .= " WHERE $primaryKey = $id";
// ...
Default
,

Encore une fois mille merci, j'avais bien fait comme cela mais pas au bon endroit .... J'ai beaucoup de mal avec les tableaux et ça ne date pas d'hier !

En tout cas merci à vous et bonne journée :-)