Problème de variables...

Eléphant du PHP | 78 Messages

14 déc. 2007, 12:30

Bonjour,

Alors je vais tenter de faire simple.

Prerequis :
1/ J'enregistre un évenement qui s'adresse a une ou plusieurs catégories. J'ai donc choisi des checkbox pour en selectionner une ou plusieurs.

2/ Je fais le traitement en enregistrant toute les checkbox dans un seul champ sql en les séparant par des tirets par exemple.
Exemple :
$categorie = ($_POST['catpou'] . '-' . $_POST['catpup'] . '-' . $_POST['catbenj'] . '-' . $_POST['catmin'] . '-' . $_POST['catcad'] . '-' . $_POST['catjun'] . '-' . $_POST['catsen'] . '-' . $_POST['catvet']);
Le problème c'est que du coup, si je n'ai pas coché les premieres par exemple, il m'enregistre ça : ----Cad--Sen-

Note : J'avais fait un calendrier et j'avais resolu le problème en effectuant une requete avec LIKE. Ici le LIKE ou le WHERE ne fonctionnent pas car le terme n'est pas précis.

Projet :
Je veux mettre les résultats de cet évenement. J'ai une liste de gens qui ont la catégorie requise pour participer. Vu qu'il y a pas mal de gens en tout, je veux faire une selection dans cette liste par la catégorie de l'évenement.

Problème :
Vu que la catégorie est imprécise, il ne me trouve rien.

Questions :
Comment faire ?

J'ai essayé par mal de chose déjà comme remplacer les tirets avec strtr mais ca ne peut pas fonctionner. En fait il faudrait enlever tout les tirets et transformer la chaine en plusieurs mots ? Dans le cas d'une chaine bien defini comme une date ca pose pas de probleme mais la c'est variable :s

Merci
Morkem

d0m
Mammouth du PHP | 1141 Messages

14 déc. 2007, 12:35

problème de conception avant tout.
Je te suggère de faire une table des catégories, une table des évenements et une table d'association.

Par exemple au lieu pour un évenement d'avoir un champ catégorie : Cad-Sen

tu auras une table de ce genre

Code : Tout sélectionner

ID_evenement | ID_categorie 1 | id_Cad 1 | id_Sen
facile ensuite de récupérer toutes les catégories d'un évenement par la requête

Code : Tout sélectionner

SELECT ID_categorie FROM table WHERE ID_evenement = 1
ou de récupérer les évenements d'une catégorie

Code : Tout sélectionner

SELECT ID_evenement FROM table WHERE ID_categorie = id_Cad

Eléphant du PHP | 78 Messages

14 déc. 2007, 12:47

Je craignais bien qu'on allait dire ça en fait ^^

Bon donc en fait oublier le champ cat dans la table even.

Ajouter une table cat avec toutes les catégories deja dedans.

Et lorsque j'enregistre un even, j'insert en même temps dans une table xxx le numero de l'even avec la ou les categories correspondantes.

J'ai bien compris le principe ?
Morkem

Avatar du membre
Modérateur PHPfrance
Modérateur PHPfrance | 10684 Messages

14 déc. 2007, 12:49

Je préconise également la solution de d0m, mais je vois pas bien ce qui te chipote dans la tienne ?

Si ton champ contient "----Cad--Sen-" une requête avec " WHERE ton_champ LIKE '%Cad%'" te retournera uniquement les enregistrement contenant le texte Cad .... je comprends pas ton histoire de "catégorie imprécise".


A noter par ailleurs, qu'au lieu de différentes cases à cocher 'catpou', 'catpup', ... tu pourrais donner le même nom à toutes tes cases et ainsi obtenir un tableau dans $_POST :

Code : Tout sélectionner

<input type="checkbox" name="categorie[]" value="Cad" /> <input type="checkbox" name="categorie[]" value="Pou" /> <input type="checkbox" name="categorie[]" value="Pup /> ...
ainsi $_POST['categorie'] est un tableau contenant les valeurs des cases qui ont été cochées qui sera plus facile à manipuler. Et si tu veux conserver le principe de valeurs séparées par un tiret, il suffit juste de faire :
$categorie = implode('-', $_POST['categorie']); 
Le résultat sera de la forme "Cad-Sen" s'il n'y a que ces deux catégories de cochées.
Ce n'est pas en améliorant la bougie que l'on a inventé l'ampoule...

Eléphant du PHP | 78 Messages

14 déc. 2007, 13:00

En fait le problème c'est que je recherche dans le champ cat de la table gens si il trouve le champ cat de l'evenement soit par exemple ----Cad--Sen-. Donc il est evident qu'il ne peut rien trouver...

En gros ca fait ca quoi : WHERE ton_champ LIKE '%----Cad--Sen-%'

Dans le cas de mon calendrier le mot qu'il recherchait dans le champ cat de l'evenement était precis (donné par une liste deroulante) donc ca ne posait pas de probleme ;)

Et admettons si je suivais ta methode, serait il possible, par rapport a ce que j'ai dit au dessus de faire une recherche par rapport au mots contenu dans ce tableau ?
Morkem

Avatar du membre
Modérateur PHPfrance
Modérateur PHPfrance | 10684 Messages

14 déc. 2007, 13:35

Oki, j'avions pas compris le sens de ta recherche.

Donc je maintiens et plussois la solution de d0m :) (de toute façon, dès le moment où tu as une cardinalité 0-N entre deux éléments (cad : un élément de l'un pouvant être associé à, de 0 à n éléments de l'autre), il faut toujours mettre en place une table intermédiaire dont la clé primaire est composée des id de chacune des autres tables :)

En ce qui concerne le nom unique des cases à cocher et la récupération des valeurs dans un tableau, je te la recommande tout de même, cela te permettra de facilement renseigner ta table intermédiaire :
// insertion de ton événement + récupération de l'id associé
...
$idEvenement = mysql_insert_id();

// boucle sur le tableau de catégorie et insertion dans la table de liaison 
foreach ($_POST['categorie'] as $idCategorieCochee) {
  $sql = "INSERT INTO ... (".$idEvenement.", ".$idCategorieCochee.")";
  mysql_query(...) or die (...) ;
}
Ce n'est pas en améliorant la bougie que l'on a inventé l'ampoule...

Eléphant du PHP | 78 Messages

18 déc. 2007, 15:52

Bon merci déjà pour tout ca...

J'ai travaillé un peu dessus et ca a l'air de fonctionner mais en fait je galere un peu pour la modification...

En fait j'ai fait une jointure du coups pour afficher tout ça :

Code : Tout sélectionner

$requete = mysql_query('SELECT * FROM even LEFT JOIN cateven ON even.id = cateven.ideven WHERE even.id='.$modifier_even);
Et derriere je recupere les données :

Code : Tout sélectionner

$categorie = $donnees['idcat'];
En fait apres avoir fait un print, je me suis rendu compte qu'il ne recuperait que la premiere... Je suis passé sur mysql et la requete est bonne c'est la facon dont je recupere qui ne l'ai pas.
En fait tout aurait été dans le meme champs j'aurais utilisé explode mais la... Il n'y a pas un moyen de tout regrouper ?
Morkem

d0m
Mammouth du PHP | 1141 Messages

18 déc. 2007, 17:04

PRemièrement, évite le

Code : Tout sélectionner

SELECT *
Précise les champs que tu veux récupérer, tu sauras au moins ce que tu as précisemment.

Sinon est que tu executes la requête et en récupères tu comme il faut les résultats en PHP?
Tu pourrais donner ton code qui fait ça?

Eléphant du PHP | 78 Messages

18 déc. 2007, 17:12

Non non la requete est correcte car je veux tout recuperer... C'est pour modifier l'evenement donc les champs seront a nouveau rempli avec ce qui etait dans la base.

Voila en fait :
if (isset($_GET['modifier_even']) AND !empty($_GET['modifier_even']))
{
$modifier_even = intval($_GET['modifier_even']);
       
$requete = mysql_query('SELECT * FROM even LEFT JOIN cateven ON even.id = cateven.ideven WHERE even.id='.$modifier_even);
$donnees = mysql_fetch_assoc($requete);
       
$nature = $donnees['nature'];
$type = $donnees['type'];
$niveau = $donnees['niveau'];
$style = $donnees['style'];
$arme = $donnees['arme'];
$categorie = $donnees['idcat'];
...
}
else
{
$nature = '';
$type = '';
$niveau = '';
$style = '';
$arme = '';
$categorie = '';
Bon et voila... Le probleme avec la requete ci dessus :
J'avais coché 4 checkbox.
Donc j'ai 4 ligne dans mysql qui correspondent a cette requete : une par chaque idcat en fait.

Je cherche le moyen de recuperer les 4 en fait. La il ne me recupere que la premiere ligne.

Je ne sais pas si m'exprime bien ?
Morkem

Avatar du membre
Modérateur PHPfrance
Modérateur PHPfrance | 10684 Messages

18 déc. 2007, 17:38

Si tu fais une jointure, tu vas récupérer autant d'enregistrement que de catégorie (et des informations redondantes), il te faut donc boucler pour récupérer chacune de tes catégorie. Si tu as coché 4 cases, tu n'as pas qu'un seule enregistrement, tu en auras 4.

L'autre solution à mon avis plus propre consiste à faire deux requêtes, l'une qui va te chercher les infos de l'article, et l'autre les id (et éventuellement les libellés, là tu peux faire une jointure) des catégories auxquelles il est associé.

Et concernant le "select *", même si tu veux tout les champs, il est quand même préférable de lister tous les champs que tu vas utiliser, tant pis si ça prend 10 secondes de plus :) Non seulement c'est plus facile pour développer/débugger parce que tu vois les index que tu auras à disposition, mais également parce que l'ordre des champs peut avoir son importance (si toi ou quelqu'un qui développe avec toi, ou après toi) utilises mysql_fetch_rows() ou mysql_fetch_array() avec les index.
Ce n'est pas en améliorant la bougie que l'on a inventé l'ampoule...

Eléphant du PHP | 78 Messages

18 déc. 2007, 17:43

Oui mais justement cette boucle elle se fait ou ? Je pensais bien faire ca mais rien ne fonctionne en fait :s
Morkem

Avatar du membre
Modérateur PHPfrance
Modérateur PHPfrance | 10684 Messages

18 déc. 2007, 17:53

Bah là, tel quel, dans ton code, ta requête dois retourner un truc du genre :

Code : Tout sélectionner

nature, type, niveau, ..., idcat(1) nature, type, niveau, ..., idcat(2) nature, type, niveau, ..., idcat(3) nature, type, niveau, ..., idcat(4)
Tu pourrais donc faire une boucle comme ceci :
$requete = mysql_query('SELECT * FROM even LEFT JOIN cateven ON even.id = cateven.ideven WHERE even.id='.$modifier_even); 

$categorie = array();

while ($donnees = mysql_fetch_assoc($requete)) {
  $nature = $donnees['nature']; 
  $type = $donnees['type']; 
  $niveau = $donnees['niveau']; 
  $style = $donnees['style']; 
  $arme = $donnees['arme']; 
  $categorie[] = $donnees['idcat']; 
  ... 
}
print_r($categorie);


Mais c'est pas terrible, tu écrases à chaque fois les valeurs de $nature, $type, etc. Donc tu pourrait éventuellement utiliser mysql_result()
$requete = mysql_query('SELECT * FROM even LEFT JOIN cateven ON even.id = cateven.ideven WHERE even.id='.$modifier_even); 

$nature = mysql_result($requete , 0, 'nature'); 
$type = mysql_result($requete , 0, 'type'); 
$niveau = mysql_result($requete , 0, 'niveau'); 
$style = mysql_result($requete , 0, 'style'); 
$arme = mysql_result($requete , 0, 'arme'); 

$categorie = array();
for (...) {
  $categorie[] = mysql_result($requete , $i, 'idcat');
  ... 
}
print_r($categorie);


Ou encore faire une seconde requête et ne boucler que sur la seconde :)
$requete = mysql_query('SELECT * FROM even WHERE even.id='.$modifier_even); 

$donnees = mysql_fetch_assoc($requete);

$nature = $donnees['nature']; 
$type = $donnees['type']; 
$niveau = $donnees['niveau']; 
$style = $donnees['style']; 
$arme = $donnees['arme']; 

$requete = mysql_query('SELECT * FROM cateven WHERE cateven.ideven='.$modifier_even); 

$categorie = array();
while ($donnees = mysql_fetch_assoc($requete)) {
  $categorie[] = $donnees['idcat'];
}
print_r($categorie);
Ce n'est pas en améliorant la bougie que l'on a inventé l'ampoule...

Eléphant du PHP | 78 Messages

18 déc. 2007, 18:16

Argh j'etais pas loin il me manquait les crochet de $categorie[]...

Sniff quel temps perdu... Merci pour tout ces exemples en tout cas je vais regarder tout ça !!

Edit : non en fait je suis un boulay... dsl..

En tous cas ça fonctionne bien... Je développe un peu le truc et je reposerais surement une tout petite question qui me vient à l'esprit... Je vais essayer de voir d'abord. Merci


Re-edit : Bon alors... En fait j'ai maintenant un soucis pour recuperer toutes les valeurs du tableau associatif de d0m et les mettre à la suite.... Comment expliquer simplement.

Sur mon index, je recupère les 5 derniers evenement et je les présente succinctement. Lorsque ces 5 derniers sont dans une même table c'est facile avec le LIMIT.
Seulement là je voudrais également les 5 derniers evenement de la table cateven or la ce n'est plus possible car il y a plusieurs catégories pour 1 evenement donc plusieurs lignes.

En gros il faudrait que pour un même id il recupere toutes les catégories et les mettent dans une variables et qu'ensuite il l'affiche avec l'evenement en question 5 fois différentes.

Vous m'avez suivi ? C'est carrement compliqué j'suis largué là... J'ai essayé en adaptant le code de Ryle mais bon. A mon avis c'est davantage une histoire de requete cette fois ci.
$requete_evenement = mysql_query('SELECT * FROM even WHERE nature="A Venir" ORDER BY date ASC LIMIT 0, 5');
$donnees_evenement = mysql_fetch_assoc($requete_evenement);

$type = $donnees_evenement['type'];
$niveau = $donnees_evenement['niveau'];
$style = $donnees_evenement['style'];
$arme = $donnees_evenement['arme'];
$numero = $donnees_evenement['numero'];
$statut = $donnees_evenement['statut'];
//Conversion de la date en FR
$a = substr($donnees_evenement['date'], 0, 4);
$m = substr($donnees_evenement['date'], 5, 2);
$j = substr($donnees_evenement['date'], 8, 2);
$date = $j.'-'.$m.'-'.$a; 

?>
<tr>
<td width="20%"><strong><?php echo ''.$date.'</strong></td> <td>'.$type.' '.$niveau.' '.$style.' '.$arme.' '.$categorie.' -'.$numero.'-'; ?></td> <td width="10%"><a href="compet/evenements.php?id_even=<?php echo $donnees_evenement['id']; ?>">Voir</a></td>
</tr>
Donc bon si admettons je refais le dernier code de ryle pour recuperer toutes les catégorie d'une id. Apres comment mettre en relation ?
Morkem

Eléphant du PHP | 78 Messages

19 déc. 2007, 20:18

Up ^^

Je galere avec 2 tables oO Je viens de lire les conseils de normalisation... Je suis encore loin d'en faire mon métier lol ;)
Morkem

Avatar du membre
Administrateur PHPfrance
Administrateur PHPfrance | 13231 Messages

20 déc. 2007, 10:14

Modération :
Morkem, les "up" sont interdits sur PHPFrance.

Si tu n'as pas obtenu de réponse, c'est (au choix) :
- que ta question est mal formulée : reformule-la différemment ;
- que personne ne connaît la réponse ici : faire un "up" ne te donnera pas davantage de résultats ;
- que la réponse demandée exige un travail important que personne ne va faire à ta place ;
- que trop peu de temps s'est écoulé depuis ton précédent message pour qu'un membre ait pu y répondre.

Merci de prendre le temps de lire les règlements.
Connaître son ignorance est la meilleure part de la connaissance
Pour un code lisible : n'hésitez pas à sauter des lignes et indenter

twitter - site perso - Github - Zend Certified Engineer