par , 28/09/2017 à 18h36 (15081 Affichages)
Je viens d'être confronté à un souci pour programmer en Ajax deux listes liées (la sélection dans l'une remplit les options de la seconde) alors que j'ai mis en oeuvre la réécriture d'URL dans mon application PHP.
1. Le déroulement des programmes PHP à l'appel d'une URL
Toutes les URL sont parsées par .htaccess et doivent être de la forme suivante : mon.site.fr/langue/Module/action avec éventuellement derrière ça un à plusieurs paramètres supplémentaires.
Mon .htaccess ressemblait à ça :
1 2
| RewriteRule ^([a-zA-Z]+)\/([a-zA-Z]+)\/([a-zA-Z_]+)\/(.+)$ index.php?langue=$1&module=$2&action=$3¶m=$4 [L]
RewriteRule ^([a-zA-Z]+)\/([a-zA-Z]+)\/([a-zA-Z_]+)$ index.php?langue=$1&module=$2&action=$3 [L] |
Apache appelle donc systématiquement le index.php de la racine de l'application.
Ce dernier récupère de $_REQUEST les paramètres standard $langue, $module et $action. Il vérifie que le module existe dans la liste des modules de l'application et lance le contrôleur du module appelé :
1 2
| // Renvoi vers le contrôleur du module demandé
require RACINE.'application/module/'.$module.'/Controller/index.php'; |
Le contrôleur du module vérifie l'existence de l'action et appelle le programme de l'action :
1 2
| // Recours au contrôleur de l'action
require RACINE.'application/module/'.$module.'/Controller/'.$action.'.php'; |
Jusque là, tout va bien...
2. La programmation des listes liées
J'ai donc deux listes que j'appellerai ici liste_mère et liste_fille. Lorsque l'utilisateur sélectionne un élément de la liste mère, un appel Ajax est fait pour restreindre la liste fille aux éléments associés à la sélection.
Dans la page HTML, la liste mère est de cette forme :
1 2 3 4 5 6
| <label for="listeMere">Mère : </label>
<select name="listeMere" onchange="restreindreFilles(this.value);"> // La propriété onchange appelle la fonction Ajax, partie Javascript.
<option value="0" selected >--Sélectionner--</option>
<option value="1">Maman</option>
<option value="2">Mother</option>
</select> |
1 2 3 4 5 6 7 8 9 10 11 12 13 14
| function restreindreFilles(mere)
{
$.ajax({
type: 'POST',
url: 'http://localhost/monappli/fr/monmodule/aj_restreindre_filles',
data: 'mere='+mere,
dataType: 'text',
cache: 'false',
success: function(filles)
{
$("#listeFille").html(filles);
}
});
} |
=> Nota : Vous aurez remarqué que j'utilise la syntaxe JQuery, tellement plus pratique !
Le programme aj_restreindre_filles est de ce genre, interrogeant la BDD afin de trouver les filles de la mère sélectionnée :
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30
| // Récupération de la mère sélectionnée par l'utilisateur (vient de la fct javascript restreindreFilles(mere)
$idMere = intval($_POST['mere']);
// Accès à la BDD et récupération de la liste des filles de cette mère
require_once RACINE.'application/include/bddMysql.php';
require_once RACINE.'application/Model/fille.php';
$obj_fille = new fille();
$liste_filles = $obj_fille->getListeFilless($idMere);
$html = '';
if(count($liste_filles) == 0)
{
// Il n'y a pas de fille pour cette mère
$html = '<option value="0">'."-- Pas de fille --".'</option>';
}
else
{
// Construction de la liste de sélection des filles correspondant à la mère choisie
$html.= '<option value="0" >-- Sélectionner --</option>'."\n";
foreach($liste_filles as $fille)
{
$html.= '<option value="'.$fille['filleId'].'" >'.$fille['filleNom'].' '.$fille['fillePrenom'].'</option>'."\n";
}
}
// Envoi de la liste des filles au programme javascript
echo $html; |
3. Le problème posé par l'URL Rewriting
L'URL appelée par le programme Javascript est interprété par le .htaccess comme s'il s'agissait d'une URL d'une page complète de l'application.
Du coup, le programme aj_restreindre_filles.php n'est pas appelé directement mais via le index.php principal de l'application puis via celui du contrôleur du module.
Une fois le programme aj_restreindre_filles.php exécuté, la main est repassée au contrôleur du module puis à index.php général... qui regénère la page HTML en entier en y incluant au début le echo $html;... et c'est l'ensemble qui est renvoyé au programme Javascript. Le code HTML de la page se retrouve donc en double dans la zone de sélection des filles... c'est la pagaille !
4. La solution
Il m'a suffi d'ajouter une règle au .htaccess pour interpréter différemment les URL contenant la chaîne 'aj_' afin qu'Apache appelle directement le programme aj_restreindre_filles.php, ce qui est la logique de la programmation en Ajax.
J'en ai profité pour ranger mes programmes Ajax/PHP dans un dossier ajax spécifique de l'arborescence de mon appli, au lieu de les répartir dans les contrôleurs des modules, ce qui, à mon avis, n'est pas vraiment leur place.
Le nouveau .htaccess avec la nouvelle règle en premier :
1 2 3
| RewriteRule ^([a-zA-Z\/]+)\/(aj_)([a-zA-Z_]+)$ application/ajax/aj_$3.php [L]
RewriteRule ^([a-zA-Z]+)\/([a-zA-Z]+)\/([a-zA-Z_]+)\/(.+)$ index.php?langue=$1&module=$2&action=$3¶m=$4 [L]
RewriteRule ^([a-zA-Z]+)\/([a-zA-Z]+)\/([a-zA-Z_]+)$ index.php?langue=$1&module=$2&action=$3 [L] |