ok, on est sur la bonne voie.
Je récapitule ce que j'ai compris:
Dans le fichier xml:
criteria.xml on trouve la liste des critères (crit) regroupée par catégorie (cat) ce qui permet de les afficher dans cette forme de regroupement dans le formulaire de recherche.
regroupement de la forme:
Code : Tout sélectionner
<root>
<cat id="1" name="cat1">
<criteria id="1" name="crit1" />
<criteria id="2" name="crit2" />
<criteria id="3" name="crit3" />
...
</cat>
<cat id="2" name="cat2">
<criteria id="1" name="crit1" />
....
</cat>
....
</root>
Dans le fichier xml:
criteria-practice.xml on trouve les associations de critères cat/crit qui déterminent un practice. association de la forme par exemple:
Code : Tout sélectionner
<root>
<link id="1">
<criteria idcat="1" idcrit="3" />
<criteria idcat="2" idcrit="1" />
...
<practice id="2" />
</link>
....
</root>
ici, le practice ayant l'id = 2 est déterminé par les couples de critères (cat/crit) = (1/3) ou (2/1)
C'est à dire que si l'utilisateur choisit dans la catégorie (cat) 1 seulement le critère (crit) 3, le practice 2 doit être trouvé par le programme de recherche et idem pour la (cat) 2 et le (crit) 1
Mais si l'on choisi dans la (cat) 1 le (crit) 3 et un autre (crit) de la (cat) 1, le practice ne doit pas être trouvé. Et idem pour la (cat) 2.
Je croix que la solution est de procéder par élimination d'un practice car si parvient à vérifier pour un (crit) x d'une (cat) y que ce (crit) x ne se trouve pas dans les <link> où sa (cat) existe, on peut alors éliminer le <link> est donc son practice.
Pour celà il faut regroupes les (crit) postés par (cat) posté et ça techniquement c'est possible car on reçoit les (cat) dans un tableau et les (crit) dans un autre dans cette forme envoyée par le formulaire.
Voici un exemple de postage du formulaire si l'on choisit les critères suivants:
- Dans la catégorie cat= 1, les critères: crit =1 et crit=2
Et Dans la catégorie cat= 2, les critères: crit =1 et crit=2
Alors:
$_POST["cat"] =
$_POST["crit"] =
On voit bien que la catégorie 1 se trouve 2 fois dans le tableau $_POST["cat"] car elle a été implicitement sélectionnée 2 fois en sélectionnant 2 de ses critères (crit)
cette redondonce est utile pour permettre l'association entre (cat) et (crit) dans les 2 tableaux, le lien étant le n° des cases.
Donc $_POST["cat"][0] est lié à $_POST["crit"][0],
$_POST["cat"][1] est lié à $_POST["crit"][1], etc...
Pour regrouper alors les critères (crit) par leur (cat) il faut faire un rapprochement entre ces 2 tableaux en utilisant le n° des cases comme indice relationnel et créer une nouvelle organisation: un tableau indexé par catégorie (ce qui permet de représenter une cat une seule fois) qui contient la liste des crit de cette cat.
Pour avoir le résultat de regroupement suivant:
$cat["1"] =
$cat["2"] =
le tableau $cat est indexé par catégorie ($cat["1"] et $cat["2"]) le "1" et "2" sont les catégories.
Ce qui permet de repèrer tous les critères d'une catégorie et les traiter ensemble. Et donc appliquer le processus de recherche des practices par élimination.
Par exemple:
pour cat=1, on prend le crit 1 (qui se trouve dans $cat["1"][0]) et on le cherche dans le fichier xml, dans les <link> où cat=1 se trouve, s'il n'existe pas alors le practice du <link> ne doit être sélectionné comme résultat.
Voici, le code du regroupement des critères par catégorie (tableau $cat)
foreach ($_POST["crit"] as $index=>$idcrit){
$idcat = $_POST["cat"][$index]; //trouve la cat du crit
$cat["$idcat"][] = $idcrit; //stocke le crit dans son groupe cat
}
il faut donc respecter cette organisation pendant la recherche, la logique est la suivante:
lors de l'exploration du xml
criteria-practice.xml on le parcourt <link> par <link> et puisque chaque <link> désigne un practice et ses critères, on vérifie chaque critère avec ceux du tableau $cat dans le cadre de la même cat par l'alternative suivante:
Code : Tout sélectionner
SI le critère xml vérifié correpond au crit posté dans $cat on marque le practice comme trouv (true)
Sinon SI ce même critère xml ne correspond pas au crit posté on marque le practice comme non
trouvé (false) et on arrête le marquage pour ce practice.
On remarque que si le marquage veut dire non trouvé (false), la vérif s'arrête immédiatement par contre quand le marquage veut dire trouvé (true) la vérif continue. C'est exactement l'équivalent d'une combinaison logique ET séquentielle (règle que tu veux établir)
Si le marquage ne s'arrête pas à non trouvé (false) la vérif continue alors et peut retrouver un état de marquage trouvé (true) qui remplace le précédent (false) et là on aura une combinaison logique OU séquentielle (que tu ne veux pas d'aileurs)
En utilisant le même marqueur par practice, la boucle de recherche met à jour le marquage selon l'alternative SI et marque par conséquant une séquence dont les états possible sont les suivants:
Code : Tout sélectionner
séquence possible pour 3 crit d'une même cat recherchés: true, true, true => practice trouvé
séquence possible pour 3 crit d'une même cat recherchés: false => practice non trouvé
séquence possible pour 3 crit d'une même cat recherchés: true, false => practice non trouvé
séquence possible pour 3 crit d'une même cat recherchés: true, true, false => practice non trouvé
Pour marquer les états d'un practice on peut utiliser un tableau de practices dont les practices doivent être uniques. Pour celà il faut indexer ce tableau par id practice.
L'algorithme est le suivant:
$practice = null;
//Recherche des practices
foreach($xml->link as $value)
{
foreach($value->criteria as $criteria)
{
//practice en cours
$id = $value->practice['id'];
//echo "<pre>"; print_r($criteria); echo "</pre>";
//Chercher selon les critères de recherche imposés
foreach($cat as $idcat=>$crit)
foreach($crit as $idcrit) //critères groupés par cat
{
//si la cat est touvée
if( trim($criteria['idcat']) == trim($idcat) )
//vérifier le crit de cette cat
if ( trim($criteria['idcrit']) == trim($idcrit) ) //si crit existe
{
$practice["$id"] = true; //sélectioner le practice en cours
}
else //au mois un crit de cette cat n'est pas trouvé
{
$practice["$id"] = false; //élinminer le practice en cours
break; //Arrêter si éliminé
}
}
}
}
echo "<pre>"; print_r($practice); echo "</pre>";
A la suite de cette moulinette, on aura un tableau $practice dont les indexes sont les id des practices rencontrés dans les <link> du xml et dont chaque case practice contient une valeur false (vide) ou true (1)
La suite du programme doit en principe utliser ce tableau pour accèder et afficher le practices trouvés. Le seul changement dans ce module existant est qu'il ne doit pas traiter les cases false du tableau practice. Pour celà on peut écrire:
//Lecture des practices trouvés
if ( (isset($practice) and count($practice) >0 )) // tableau des practices
{
foreach ($practice as $id=>$trouvé){
if (!$trouvé) continue; //sauter les practices marqués non trouvés
//fichier qui contient toutes les practices
$practicesFile = $cfg['ressources_root'].'/content/practice/'.$id.'.xml';
....