Aller au contenu

Problème de type array multi-dimensions


Sujets conseillés

Posté

Bonjour à tous !

Pour une appli de gestion des stocks, je crée un array à partir des données d'une table.

Je récupère l'id produit ainsi que les valeurs des options (couleurs et tailles) pour chaque produit.

Ce tableau multi-dimensions, une fois créé, se présente ainsi (exemple sur deux produits) et est stocké dans une variable $tableau :

array(array(102,array(10,11,13,14,49,50),array(1,2,5,6,7,8)),array(183,array(41,44,47,50),array(5,6,7,8)))

Ce code fonctionne très bien lorsque je code "en dur" $tableau :

$ tableau = array(array(102,array(10,11,13,14,49,50),array(1,2,5,6,7,8)),array(183,array(41,44,47,50),array(5,6,7,8)))

Voici le code que j'utilise pour l'exploiter :

function afficher_tableau($tableau)
{
// on fait une boucle qui lit les éléments du tableau
foreach ($tableau as $cle=>$valeur)
{
// si l'un des éléments est lui même un tableau
// alors on applique la fonction à ce tableau
if(is_array($valeur))
{
// on affiche le nom de la clé et
// le début d'une liste pour
// décaler le contenu vers la droite
echo $cle.' : <ul>';

// ici se réalise la récursivité
// c'est à dire qu'on applique la fonction
// à l'élément en cours car c'est lui aussi un tableau
afficher_tableau($valeur);

// on ferme la liste
echo '</ul>';
}

// si ce n'est pas un tableau
// alors on affiche le contenu de l'élément
else
{
echo $cle.' = '.$valeur.' <br>';
}
}
}

Seulement, lorsque je veux exploiter le $tableau créé à partir de ma requête SQL, je me retouve avec cette erreur :

Warning: Invalid argument supplied for foreach() in etc...

Logique, puisque lorsque je fais un gettype(), il me retourne qu'il s'agit d'un type String.

Forcer le type par un settype($tableau, "array"); ne fonctionne pas.

Des idées ?

Merci d'avance !

(testé sous PHP 4.3.0 et 5.x)

Posté

Salut ;)

Effectivement ce code marche bien, et c'est donc le code qui crée le tableau qui ne marche pas... Mais tu ne nous le donnes pas, donc on va pas pouvoir t'aider :P

Donne donc le code qui te crée le tableau à partir de ta base ;) c'est de là que vient l'erreur.

Posté (modifié)

Merci de ta réponse Sarc,

pour moi, la "création" de l'array fonctionne, je la vérifie par un echo qui m'affiche bien ce que j'attendais... mais j'ai (forcément) loupé qq chose :(

voici donc le code intégral de la page :


<?php
// on se connecte à MySQL
$db = mysql_connect('localhost', 'root', ''); // connexion en local

// on sélectionne la base
mysql_select_db('mabase',$db);

// on crée la requête SQL
$sql = 'SELECT * FROM products_attributes ORDER BY products_id, options_id, options_values_id';

// on envoie la requête
$req = mysql_query($sql) or die('Erreur SQL !<br>'.$sql.'<br>'.mysql_error());
$total = mysql_num_rows($req); // nb total d'enregistrements

?>
<html xmlns="http://www.w3.org/1999/xhtml">
<head>
<meta http-equiv="Content-Type" content="text/html; charset=iso-8859-1" />
</head>

<body>
<?
// initialisation des compteurs
$enregistrement=0;
$id_produit_old = 0;
$id_option_old = 0;

// on fait une boucle qui va faire un tour pour chaque enregistrement
// début de la boucle, on initialise la chaine avec le tableau principal (
$product_attributes_chaine = 'array(';

while($data = mysql_fetch_assoc($req))
{

// on doit arriver à un tableau de ce genre :
// $product_attributes = array(array (products_id1,array(options_values_id où options_id=1,...),array(options_values_id où options_id=2, ...)), array( array(products_id2,array(options_values_id où options_id=1,...),array(options_values_id où options_id=2, ...)));

// on incrémente le compteur d'enregistrements
$enregistrement ++;
$id_produit = $data['products_id'];
$id_option = $data['options_id'];
$options_values_id = $data['options_values_id'];

switch($id_produit_old) // on vérifie l'id produit
{
case 0: // premier enregistrement -> on commence un nouveau tableau
$product_attributes_chaine .= 'array(' . $id_produit . ',array(' . $options_values_id;
$id_produit_old = $id_produit;
$id_option_old = $id_option;
break;

case $id_produit: // on est sur le même produit -> on continue le tableau

switch($id_option_old) // on vérifie l'id_option_old
{
case 0: // première boucle -> on pose la première valeur
$product_attributes_chaine .= $options_values_id;
$id_option_old = $id_option;
break;

case $id_option: // on est toujours sur le meme numero d'option -> on continue le tableau

switch ($enregistrement) // on vérifie le n° d'enregistrement
{
case $total: // on a atteint le dernier enregistrement, on clôt tous les array
$product_attributes_chaine .= ',' . $options_values_id . ')))';
$id_option_old = $id_option;
break;

default: // ce n'est pas le dernier enregistement, on continue le tableau
$product_attributes_chaine .= ',' . $options_values_id;
$id_option_old = $id_option;
break;
}

break;

default: // on change de numero d'option

switch($id_option) // on vérifie l'id_option
{
case 2: // si l'id_option passe de 1 à 2, on ferme le premier tableau et on commence le second
$product_attributes_chaine .= '),array(' . $options_values_id;
$id_option_old = $id_option;
break;
case 1: // si l'id_option passe de 2 à 1, on ferme le second tableau et on recommence un array avec le nouveau products_id
$product_attributes_chaine .= '),array(' . $id_produit . ',array(' . $options_values_id;
$id_option_old = $id_option;
break;

} // fin switch id_option

break;
} // fin switch id_option_old

$id_produit_old = $id_produit;
break;

default: //on change de produit
// si c'est le dernier produit de la table, on ferme le second tableau
$product_attributes_chaine .= ')';
$id_produit_old = $id_produit;
break;
}
}// fermeture du while
// on ferme la connexion à mysql
mysql_close();
// le tableau complet est dans $product_attributes_chaine

echo $product_attributes_chaine; // affichage de vérification du tableau, il me donne bien ce que j'escomptais...

$chaine = $product_attributes_chaine;
echo "<br>type " . gettype( $chaine ) . "<br />\n";

afficher_tableau($chaine);

function afficher_tableau($tableau)
{
// if (is_array($tableau))
// {
// on fait une boucle qui lit les éléments du tableau
foreach ($tableau as $cle=>$valeur)
{
// si l'un des éléments est lui même un tableau
// alors on applique la fonction à ce tableau
if(is_array($valeur))
{
// on affiche le nom de la clé et
// le début d'une liste pour
// décaler le contenu vers la droite
echo $cle.' : <ul>';

// ici se réalise la récursivité
// c'est à dire qu'on applique la fonction
// à l'élément en cours car c'est lui aussi un tableau
afficher_tableau($valeur);

// on ferme la liste
echo '</ul>';
}

// si ce n'est pas un tableau
// alors on affiche le contenu de l'élément
else
{
echo $cle.' = '.$valeur.' <br>';
}
}

// }
}
?>
</table>
</body>
</html>

Modifié par Keyser Soze
Posté

Tu as le BBCode [ codebox ] [/ codebox ] pour les longs codes, si tu veux, ça évite de devoir défiler sur toute la page pour lire les réponses d'après ;)

pour moi, la "création" de l'array fonctionne, je la vérifie par un echo qui m'affiche bien ce que j'attendais... mais j'ai (forcément) loupé qq chose

C'est bien ce qui m'inquiétais, tu ne crées qu'une chaîne de caractère qui donne le code de création d'un tableau en PHP, mais tu ne crées pas un tableau ! Voilà pourquoi ça pose problème...

Ton code est assez compliqué et je n'ai pas le temps de le parcourir en profondeur, mais tu sais ce qu'il faut pour créer un tableau...

Par exemple :

// Construction d'un sous-tableau
$soustab1 = array('1', '2', '3');

// Rajout de ce sous-tableau à la suite du tableau principal
$tableau[] = $soustab1;

Voilà ce que tu dois faire, commencer par construire tes sous-tableaux, puis construire ton tableau principal du genre

$tableau = array($soustab1, $soustab2);

Et si tu veux rajouter un élément dans ce tableau, tu fais :

$tableau[] = $soustab3;

Voilà en gros comment revoir ton code ;) Bonne chance !

Posté

Effectivement... ta solution me semble tellement évidente que je me demande pourquoi je n'y ai pas pensé ! *va se flageller avec une botte d'orties et revient*

Je la teste ce soir et je te dis ce qu'il en est.

Merci encore pour cette illumination ! ;)

Posté (modifié)

Voici le code qui fonctionne (grâce aux lumières de Sarc ;)) Je le poste pour ceux qui seraient confrontés au même type de problème.

Son utilité ? Pour les sites marchands sous OS Commerce lorsque vous vous retrouvez confrontés à une demande de gestion précise des stocks où, pour chaque article, vous devez connaître les quantités disponibles pour chaque déclinaison de couleurs et de tailles entre elles... Le développement de l'appli est en cours, ceci en constitue la première partie.

Encore merci pour le coup de main !

<?php
// on se connecte à MySQL
$db = mysql_connect('localhost', 'root', ''); // local

// on sélectionne la base
mysql_select_db('mabase',$db);

// on crée la requête SQL
$sql = 'SELECT * FROM products_attributes ORDER BY products_id, options_id, options_values_id';

// on envoie la requête
$req = mysql_query($sql) or die('Erreur SQL !<br>'.$sql.'<br>'.mysql_error());
$total = mysql_num_rows($req); // nb total d'enregistrements

?>
<!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Transitional//EN" "http://www.w3.org/TR/xhtml1/DTD/xhtml1-transitional.dtd">
<html xmlns="http://www.w3.org/1999/xhtml">
<head>
<meta http-equiv="Content-Type" content="text/html; charset=iso-8859-1" />
<title>Constitution Tableau</title>
</head>

<body>
<?
// initialisations
$compteur = 0;
$id_produit_old = 0;
$tableau = array();
$soustableau1 = array();
$soustableau2 = array();
$soustableau3 = array();
$soustableau4 = array();

// on fait une boucle qui va faire un tour pour chaque enregistrement

while($data = mysql_fetch_assoc($req))
{
// incrémentation compteur
$compteur ++;

$id_produit = $data['products_id'];
$id_option = $data['options_id'];
$id_valeur_option = $data['options_values_id'];

echo $id_produit . "-" . $id_option . "-" . $id_valeur_option . "<br>";

switch($id_produit) // on vérifie l'id produit
{
case $id_produit_old: // on continue le meme produit
switch ($id_option) // on vérifie le numero d'option et on l'ajoute au sous tableau concerné
{
case 1: //
$soustableau1[] = $id_valeur_option ;
break;
case 2: //
$soustableau2[] = $id_valeur_option ;
break;
case 3: //
$soustableau3[] = $id_valeur_option ;
break;
case 4: //
$soustableau4[] = $id_valeur_option ;
}// fermeture du switch $id_option

switch ($compteur) // on vérifie si c'est le dernier enregistrement
{
case $total:// on arrive au dernier produit
$tableau[$id_produit] = array(1=>$soustableau1,2=>$soustableau2, 3=>$soustableau3, 4=>$soustableau4);
}
break; // break $id_produit_old

case ($id_produit_old != $id_produit) : // on change de produit ou on commence le tableau
switch ($compteur)
{
case 1: // on commence le tableau
switch ($id_option) // on vérifie le numero d'option et on l'ajoute au sous tableau concerné
{
case 1: //
$soustableau1[] = $id_valeur_option ;
break;
case 2: //
$soustableau2[] = $id_valeur_option ;
break;
case 3: //
$soustableau3[] = $id_valeur_option ;
break;
case 4: //
$soustableau4[] = $id_valeur_option ;
}// fermeture du switch $id_option
break;

case $total:// on arrive au dernier produit
switch ($id_option) // on vérifie le numero d'option et on l'ajoute au sous tableau concerné
{
case 1: //
$soustableau1[] = $id_valeur_option ;
break;
case 2: //
$soustableau2[] = $id_valeur_option ;
break;
case 3: //
$soustableau3[] = $id_valeur_option ;
break;
case 4: //
$soustableau4[] = $id_valeur_option ;
}// fermeture du switch $id_option
$tableau[$id_produit] = array(1=>$soustableau1,2=>$soustableau2, 3=>$soustableau3, 4=>$soustableau4);
break;

default: // on change de produit
$tableau[$id_produit_old] = array(1=>$soustableau1,2=>$soustableau2, 3=>$soustableau3, 4=>$soustableau4);
// on réinitialise le contenu des sous tableaux
$soustableau1 = array();
$soustableau2 = array();
$soustableau3 = array();
$soustableau4 = array();
switch ($id_option) // on vérifie le numero d'option et on l'ajoute au sous tableau concerné
{
case 1: //
$soustableau1[] = $id_valeur_option ;
break;
case 2: //
$soustableau2[] = $id_valeur_option ;
break;
case 3: //
$soustableau3[] = $id_valeur_option ;
break;
case 4: //
$soustableau4[] = $id_valeur_option ;
}// fermeture du switch $id_option
}
$id_produit_old = $id_produit ;
}// fermeture du switch $id_produit

}// fermeture du while

// on ferme la connexion à mysql
mysql_close();
// le tableau complet est dans $tableau

afficher_tableau($tableau);

function afficher_tableau($array)
{
// if (is_array($tableau))
// {
// on fait une boucle qui lit les éléments du tableau
foreach ($array as $cle=>$valeur)
{
// si l'un des éléments est lui même un tableau
// alors on applique la fonction à ce tableau
if(is_array($valeur))
{
// on affiche le nom de la clé et
// le début d'une liste pour
// décaler le contenu vers la droite
echo $cle.' : <ul>';

// ici se réalise la récursivité
// c'est à dire qu'on applique la fonction
// à l'élément en cours car c'est lui aussi un tableau
afficher_tableau($valeur);

// on ferme la liste
echo '</ul>';
}

// si ce n'est pas un tableau
// alors on affiche le contenu de l'élément
else
{
echo $cle.' = '.$valeur.' <br>';
}
}

// }
}
?>
</table>
</body>
</html>

Modifié par Keyser Soze

Veuillez vous connecter pour commenter

Vous pourrez laisser un commentaire après vous êtes connecté.



Connectez-vous maintenant
×
×
  • Créer...