Filtrer un tableau multidimentionnel

Eléphanteau du PHP | 11 Messages

14 avr. 2010, 15:05

Bonjour et merci à ceux qui m'ont déjà bien aidé dans mon apprentissage du PHP et Mysql,

Je tourne en rond depuis plusieurs jours sur ce problème :

Constructeur

Code : Tout sélectionner

+---------------------+---------------------+ | id_constructeur | Constructeur | +---------------------+---------------------+ | 1 | Renault | +---------------------+---------------------+ | 2 | Citroen | +---------------------+---------------------+ | 3 | Peugeot | +---------------------+---------------------+
stock

Code : Tout sélectionner

+---------------------+---------------------+---------------------+ | id_constructeur | Categorie | Modele | +---------------------+---------------------+---------------------+ | 1 | Citadine | Clio | +---------------------+---------------------+---------------------+ | 1 | Citadine | Twingo | +---------------------+---------------------+---------------------+ | 1 | Berline | Megane | +---------------------+---------------------+---------------------+ | 2 | Citadine | Saxo | +---------------------+---------------------+---------------------+ | 2 | Monospace | Picasso | +---------------------+---------------------+---------------------+ | 1 | Berline | Laguna | +---------------------+---------------------+---------------------+ | 3 | Berline | 407 | +---------------------+---------------------+---------------------+ | 3 | Citadine | 106 | +---------------------+---------------------+---------------------+ | 3 | Monospace | 806 | +---------------------+---------------------+---------------------+
J'arrive maintenant à afficher :
Renault : Citadine: Clio, Twingo - Berline: Megane, Laguna
* Citroen: Citadine: Saxo - Monospace: Picasso
* Peugeot: Citadine: 106 - Berline: 407 - Monospace: 806
avec
$sql = "SELECT constructeur.id_constructeur, constructeur.constructeur  stock.categorie,stock.modele
FROM stock JOIN constructeur 
ON constructeur.id_constructeur = stock.id_constructeur

$req = mysql_query($sql) or die('Erreur SQL !<br>'.$sql.'<br>'.mysql_error()); 
while ($data = mysql_fetch_array($req) )
{
$tableau[$data['constructeur']][$data['categorie']][] = $data['modele'];
}


if (isset($tableau))
{
$i = 1;


foreach ($tableau as $cle1=>$valeur1) 
{
    
    if ($i === 1)
{
            $str .= $cle1 . ": ";
             
             }
    else
            {
            $str .= "* ".$cle1 . ": ";
            
              }
$i++;
$j = 1;
foreach ($valeur1 as $cle2=>$valeur2) 
{

    if ($j === 1)
{
      $str .= "Cat: ".$cle2 . ": ";
       
              }
    else
            {
            $str .= " - Cat: ".$cle2 . ": ";
             
   }           
         
 $j++; 
      
    foreach ($valeur2 as $cle3=>$valeur3) 
    {
    
    $str .= $valeur3. " ";
    
}
}

}

}

else
{
echo "Pas de données a afficher";
}
echo "<br>";


echo $str;
Maintenant je voudrais pouvoir filtrer mon tableau par carburants afin d'avoir par exemple un résultat avec les citadine & berlines essence de tous les constructeurs et les monospaces diesels
de tous les constructeurs



J'ai pensé à creer une nouvelle table :

Code : Tout sélectionner

+---------------------+---------------------+ | Categorie| Carburant | +---------------------+---------------------+ | Citadine | 0 ou 1| +---------------------+---------------------+ | Berline | 0 ou 1| +---------------------+---------------------+ | Monospace | 0 ou 1 | +---------------------+---------------------+

Carburant
0 = essence
1 = diesel

Avec une case à cocher dans un formulaire j'UPDATE la valeur 0 ou 1

Par conséquent je modifie ma requete pour y inclure le champ carburant, ce qui me retourne un tableau mais je n'arrive pas à filtrer ce tableau sur la condition 'carburant'

J'aurais voulu eviter de faire 2 requetes distinctes

J'ai essayé d'utilser la fonction array_filter mais sans succès.

Quelqu'un a t'il une pour que je puisse avancer ?

En vous remerciant.

ViPHP
ViPHP | 928 Messages

14 avr. 2010, 16:09

Ca me rappel plein de souvenirs ce que tu fais, vu que j'ai fait les configurateurs des nouveaux sites Peugeot ^^

Côté requête SQL, pour filtrer par essence avec tes tables voilà ce que tu dois faire :
SELECT c.id_constructeur, c.constructeur, s.categorie, s.modele
FROM stock s
JOIN constructeur c ON c.id_constructeur = s.id_constructeur
JOIN essence e ON e.categorie = s.categorie
WHERE e.carburant = 1
(en mettant 0 ou 1 suivant le type de carburant)

Mammouth du PHP | 672 Messages

14 avr. 2010, 17:39

:?:
Je ne comprends pas tout...
Ou plutôt j'ai peur de comprendre...

Les 0/1 servent à quoi ? Tu veux dire que toutes les berlines seront forcément essence (ou diesel) ?
Ou alors tu mets cette table à jour à chaque consultation ? Mais dans ce cas, pour quoi faire, vu qu'on ne retrouve nulle part ailleurs de distinction essence/diesel ?

Je te conseille fortement de revoir le schéma de ta base de données, parce que là ta nouvelle table n'a aucun lien avec les autres - ce qui veut dire qu'il y a un problème.
Ou alors elle est liée à ta table STOCK, ce qui veut dire que tu ne peux avoir qu'un type de moteur par type de voiture...

Eléphanteau du PHP | 11 Messages

14 avr. 2010, 21:03

Tout d'abord merci pour vos réponses qui me permettent de voir que je me suis trompé dans l'énoncé de ma question. En effet l'histoire des carburants viendra plus tard mais pour l'instant oublions là.

La question est que je voudrais faire un "filtre" sur les catégories.

J'ai donc creer une table filtre_cat

+---------------------+---------------------+
| Categorie| Actif |
+---------------------+---------------------+
| Citadine | 0 ou 1|
+---------------------+---------------------+
| Berline | 0 ou 1|
+---------------------+---------------------+
| Monospace | 0 ou 1 |
+---------------------+---------------------+

où "actif" sert de parametre pour le filtre (je ne suis pas sur que ce soit une méthode très php)

Je m'explique :

J'ai crée une requete sur l'ensemble de la table stock ce qui me permet de construire un tableau multidimentionnel
$tableau[constructeur][categorie][modele]

Sur ce tableau je voudrais par exemple isoler la categorie berline de tous les constructeurs.
Pour ce faire je pense passer le champ "actif" à 1 de façon à filtrer comme je le ferais dans une requete sql avec : where actif ='1'

Si je repars de mon 1er exemple je cherche à avoir comme résultat

resultat 1 : Renault : Citadine: Clio, Twingo * Citroen: Citadine: Saxo - Monospace: Picasso * Peugeot: Citadine: 106 - Monospace: 806

resultat 2 : Renault : Berline: Megane, Laguna * Peugeot : Berline: 407

Si c'etait possible j'aurais voulu faire ça directement sur le 1er tableau et ainsi eviter la methode de Genova qui m'oblige a faire 2 requetes.

En vous remerciant,

Mammouth du PHP | 672 Messages

15 avr. 2010, 13:48

Et en rajoutant une clause du genre WHERE categorie='berline' ?

En fait, quand tu parles de tableau, tu parles du résultat ?

Eléphanteau du PHP | 11 Messages

15 avr. 2010, 14:28

Merci Macgawel pour ta réponse.

1) Oui $tableau est le résultat

2) J'ai bien pensé au WHERE mais ce la m'oblige
1) de refaire des requetes sur les tables alors que j'ai les infos dans $tableau
2) de devoir concatener 2 requetes dans le tableau si je veux par exemple isoler les monospaces de tous les constructeurs, puis toutes les autres categories de tous les constructeurs.

Mammouth du PHP | 672 Messages

15 avr. 2010, 17:14

2) J'ai bien pensé au WHERE mais ce la m'oblige
1) de refaire des requetes sur les tables alors que j'ai les infos dans $tableau
2) de devoir concatener 2 requetes dans le tableau si je veux par exemple isoler les monospaces de tous les constructeurs, puis toutes les autres categories de tous les constructeurs.
OK.
Donc tu as récupéré toutes les infos nécessaires dans un tableau PHP...

=> Plus besoin de SQL, le traitement se fait sur ton tableau PHP.
Si j'ai bien suivi, il est sous cette forme :

Code : Tout sélectionner

$tableau ['Renault'] ['Citadine'] [0] = 'Clio' $tableau ['Renault'] ['Citadine'] [1] = 'Twingo' $tableau ['Renault'] ['Berline'] [0] = 'Megane' $tableau ['Citroen'] ['Citadine'] [0] = 'Saxo'
Et tu voudrais que ton affichage HTML sorte un tableau avec tout sauf les berlines, et un autre avec uniquement les berlines.

En gros :
- Soit tu utilises array_filter() pour générer un tableau avec tout sauf les berlines et un autre avec uniquement les berlines. Et ensuite tu gères l'affichage.
- Soit tu boucles sur $tableau2, et tu testes :
SI c'est une berline, on alimente la chaine de caractères $affichage_berlines (avec la mise en forme qui va bien)
SINON on alimente la chaine de caractères $affichage_autre
Et ensuite tu fais un echo pour afficher le contenu de tes variables...

Eléphanteau du PHP | 11 Messages

16 avr. 2010, 00:41

Merci encore une fois de me répondre.

J'avais déjà imaginer utiliser ces 2 methodes en me disant que c'etait par là que je trouverais la solution.
Cependant je me suis retrouver face a différentes interrogations.

1) Je n'ai pas été foutu de définir la fonction qui me permettrait de filtrer avec array_filter() l'equivalent de WHERE actif ='1'
2) Dans le cas d'une boucle, comme categorie est le 2eme array j'arrive effectivement à ne pas faire s'afficher une categorie where actif='1' mais par exemple si c'est un constructeur qui n'a que des berlines il m'affiche quand même le constructeur.

Exemple : Ici Peugeot n'a que des berlines

resultat 1 : Renault : Citadine: Clio, Twingo * Citroen: Citadine: Saxo - Monospace: Picasso * Peugeot:

resultat 2 : Renault : Berline: Megane, Laguna * Peugeot : Berline: 407

Je continue à chercher !

Mammouth du PHP | 661 Messages

16 avr. 2010, 02:02

et pourquoi ne formates tu pas ton tableau tel que tu en a besoin en sortie de MySQL ?

si tu séparer tes données en types de véhicules, il te suffirait de monter ta variable comme ça :

while ($data = mysql_fetch_array($req) )
{
$tableau[$data['categorie']][$data['constructeur']][] = $data['modele'];
}

et t'en parles plus ... non ?

Eléphanteau du PHP | 11 Messages

16 avr. 2010, 12:39

Merci à vous tous de vous pencher sur mon problème.

@Nours312:
Si j'applique ta méthode je vais avoir en sortie :

Cat. Cidatines : Renault : Clio, Twingo - Citroen : Saxo - Peugeot : 106
Cat. Monospaces : Citroen : Picasso - Peugeot : 807
puis
Cat. Berlines : Renault : Megane, Laguna - Peugeot : 407

Donc là aussi 2 pb se posent à moi (désolé je débute en PHP MySql alors s'il y a des choses qui pour vous parraisent évidentes, pour moi je les découvre)

1) En terme d'affichage, comment j'arrive à :

Exemple : Ici Peugeot n'a que des berlines

resultat 1 : Renault : Cat. Citadine: Clio, Twingo * Citroen: Cat. Citadine: Saxo - Cat. Monospace: Picasso * Peugeot:

resultat 2 : Renault : Cat. Berline: Megane, Laguna * Peugeot : Berline: 407

2) Comment je filtre sur mon champ filtre_cat.actif ?

Je m'aperçois que la réponse n'est pas évidente.

Je pense que le meilleur moyen serait d'utiliser le array_filter mais j'ai du mal à crée la fonction qui permet de selectionner une catégorie quand le champ champ filtre_cat.actif ='1' .

J'ai essayé aussi la methode basée sur 2 requetes sql et en faisant un array_merge des 2 tableaux issues du mysql_fetch_array mais le pb c'est que le 2eme ecrase le premier car ils ont les meme clés.

Je continue à chercher.

Mammouth du PHP | 661 Messages

16 avr. 2010, 14:06

donc, je reprend :

tu as un tableau du style :

$t = array( berline => array( ...) , citadine => array() ..

$berlines = $t['berline'] ;

unset($t['berline'])

$autresTypes = $t ....

c'est bon ça !?

EDIT :
tu peux aussi ensuite répartir depuis une boucle ... faite dans $autreTypes
OU
faire le tri définitifs dans deux tableaux au lieu d'un seul directement dans ta réponse mysql ...
$tableauBerline = array();
$tableau = array();
while ($data = mysql_fetch_array($req) )
{
    if ($data['categorie'] == "berline")
       $tableauBerline[$data['constructeur']][$data['categorie']][] = $data['modele'];
    else
       $tableau[$data['constructeur']][$data['categorie']][] = $data['modele'];
}


Eléphanteau du PHP | 11 Messages

16 avr. 2010, 22:26

Super ça marche !!!!!

Merci beaucoup