Bonnes pratiques : AJAX et WordPress
Plus de 6 minutes 🙂
Introduction
Voilà une demande qui se fait souvent, comment faire proprement de l’ajax dans une installation WordPress,que se soit dans un plugin, dans l’admin ou dans sur le front.
Heureusement, WordPress propose une toute petit API pour faire de l’ajax très facilement et profiter de toutes les fonctionnalités de WordPress dans son PHP.
Les actions
WordPress proposant son APi pour faire de l’ajax, nous avons deux actions disponibles :
'wp_ajax_' 'wp_ajax_nopriv_'
Pour que WordPress comprenne bien ces actions, il faut tout simplement lui signifier l’action que nous voulons effectuer :
[pastacode provider= »manual » lang= »php »]
add_action( 'wp_ajax_getPost', 'get_the_posts' );
[/pastacode]
ou
[pastacode provider= »manual » lang= »php »]
add_action( 'wp_ajax_nopriv_getPost' , 'get_the_posts' );
[/pastacode]
Comme on peut le voir, j’ai ajouté ‘getPost’ à la fin des noms des actions, c’est le nom de l’action que nous voulons faire. Mais il y a aussi une nuance, le petit ‘no_priv’ à la fin de l’action.
Que signifient-ils ? Tout simplement qui si on ajoute pas le ‘nopriv’ dans le nom de notre action, la fonction appelée par l’action ne sera active que pour les utilisateurs non connectés. Si vous faites un plugin qui s’adresse aux deux types d’utilisateurs ou alors un plugin qui ne fait de l’ajax que dans l’admin ces actions peuvent appeler des fonctions totalement différentes.
Cas d’étude
Nous allons faire un tout petit script qui va mettre en évidence les deux actions. Nous voulons mettre en bas d’article un lien qui donne accès à des informations supplémentaires mais qui ne sont affichées qu’aux utilisateurs connectés. Notre plugin se composera d’un fichier php et d’un fichier javascript qui va gérer la requête ajax.
Le code PHP
Ajouter le lien en bas d’article
Ajoutons donc un lien en fin d’article, pour que se soit très propre nous allons le faire avec le filtre sur ‘the_content’.
[pastacode provider= »manual » lang= »php »]
add_filter( 'the_content', 'add_content_ajax_link' );
function add_content_ajax_link( $content ) {
$content .= '
'; return $content; }
[/pastacode]
Nous venons juste d'ajouter à notre article un lien qui ne renvoie vers rien mais qui nous permettra de faire notre petit javascript.
Ajouter l'action et la réponse
Pour que WordPress comprenne notre demande nous devons faire une requête spécifiquement vers une url, la ajaxurl. Si vous regardez bien dans l'admin avec la source, il y a des variables javascript dans le header :
Cette variable est la même pour tous les blogs et se base su l'url de l'admin, mais n'est pas dans les variables javascript dans le front. Il faut que nous l'ajoutions manuellement pour que le code puisse fonctionner même si l'url du site change.
Ajout de l'action ajax
Quelle que soit l'action ajax que vous allez faire, il faut faire un die ou un exit à la fin de votre script ou WordPress le fera pour vous, mais accompagnera votre résultat d'un 0, ce qui ne vous arrangeras pas forcément.
[pastacode provider="manual" lang="php"]
// Action pour l'utilisateur connecté
add_action( 'wp_ajax_ajaxLink', 'a_ajaxLink' );
function a_ajaxLink(){
echo __( 'The date is ' ).date( 'd m Y' );
die();
}
// Action pour l'utilisateur non connecté
add_action( 'wp_ajax_nopriv_ajaxLink', 'an_ajaxLink' );
function an_ajaxLink(){
echo __( 'You have to be logged in for more infos.' );
die();
}
[/pastacode]
Nous avons donc deux résultats différents pour chaque action ajax envoyée, j'ai préfixé les fonctions d'un 'a' pour l'appel ajax connecté et d'un 'an' pour l'appel en nopriv.
Nous allons maintenant devoir ajouter le javascript et la variable vers l'API ajax de WordPress dont nous avons parlé plus tôt.
Ajout du javascript et de la variable
Nous allons ajouter ce code dans le fichier functions.php:
[pastacode provider="manual" lang="php"]
// Ajoutons le script dans le wp_head
add_action( 'init', 'add_ajax_script' );
function add_ajax_script() {
if( !is_single() )
return false;
wp_enqueue_script( 'ajax_link', template_url().'/js/ajax_link.js', array( 'jquery' ), '1.0', true );
wp_localize_script( 'ajax_link', 'aLink', array( 'ajaxurl' => admin_url( '/admin-ajax.php' ) ) );
}
[/pastacode]
La fonction wp_enqueue_script accepte 5 paramètres:
- l'identifiant unique du script pour WordPress
- L'url du script à importer
- La dépendance du script, ici il faut jQuery pour que ça marche car nous allons utiliser le jquery de WordPress
- La version de notre script ( utile pour le cache en cas de mise à jour )
- Forcer le script à s'ajouter dans le footer. Cette valeur est à false pas défaut, en la mettant à true le script sera ajouté au moment du wp_footer.
- L'identifiant du script qui utilise la variable
- Le nom de la variable javascript qui sera créée
- Un tableau de clé/valeurs qui vous permettent de passer des variables PHP très facilement, ou des chaînes traduites !
Le javascript
[pastacode provider="manual" lang="javascript"]
jQuery( function() {
jQuery( '.ajax_link_wrapper' ).on('click', 'a.ajax_link', function( event ){
event.preventDefault();
var _self = jQuery( this ),
parent = jQuery( this ).closest( 'div' );
if( !parent.hasClass( 'ajaxing' ) ) {
jQuery.ajax( {
url: aLink.ajaxurl,
type: "POST",
data: { action : 'ajaxLink' },
beforeSend: function() {
parent.addClass( 'ajaxing' );
},
success: function( response ) {
parent.removeClass( 'ajaxing' );
response.appendTo( parent );
}
} );
}
});
});
[/pastacode]
Dans ce javascript tout simple, nous faisons une requête vers notre API de WordPress avec le "aLink.ajaxurl", et pour éviter de lancer plusieurs fois notre action ajax nous ajoutons la classe "ajaxing" à notre parent que nous retirons lors de la fin de notre requête.
Maintenant en cliquant sur notre lien, nous allons faire une requête ajax et ajouter le résultat dans notre parent.
Le script final
Le PHP
[pastacode provider="manual" lang="php"]
add_filter( 'the_content', 'add_content_ajax_link' );
function add_content_ajax_link( $content ) {
$content .= '
'; return $content; } // Action pour l'utilisateur connecté add_action( 'wp_ajax_ajaxLink', 'a_ajaxLink' ); function a_ajaxLink() { echo _( 'The date is ' ).date( 'd m Y' ); die(); } // Action pour l'utilisateur non connecté add_action( 'wp_ajax_nopriv_ajaxLink', 'an_ajaxLink' ); function a_ajaxLink() { echo _( 'You have to be logged in for more infos.' ); die(); } // Ajoutons le script dans le wp_head add_action( 'init', 'add_ajax_script' ); function add_ajax_script() { // Testons si nous sommes bien dans un article seul if( !is_single() ) return false; wp_enqueue_script( 'ajax_link', template_url().'/js/ajax_link.js', array( 'jquery' ), '1.0', true ); wp_localize_script( 'ajax_link', 'aLink', array( 'ajaxurl' => admin_url( '/admin-ajax.php' ) ) ); }
[/pastacode]
Le Javascript
[pastacode provider="manual" lang="javascript"]
jQuery( function() {
jQuery( '.ajax_link_wrapper' ).on( 'click' , 'a.ajax_link', function( event ){
event.preventDefault();
var _self = jQuery( this ),
parent = jQuery( this ).closest( 'div' );
if( !parent.hasClass( 'ajaxing' ) ) {
jQuery.ajax( {
url: aLink.ajaxurl,
type: "POST",
data: { action : 'ajaxLink' },
beforeSend: function() {
parent.addClass( 'ajaxing' );
},
success: function( response ) {
parent.removeClass( 'ajaxing' );
response.appendTo( parent );
}
} );
}
});
});
[/pastacode]
Conclusion
Faire de l'ajax dans WordPress est très aisé, mais il faut garder en tête que chaque actions que vous allez laisser à votre utilisateur doit être testée et vérifiée.
Il faut que si vous permettez des actions, que ces actions ne puissent pas laisser une personne mal intentionnée de casser votre site.
Pour aller plus loin
Une classe existe pour ajouter facilement des actions ajax juste en formattant vos méthodes avec des 'a_' ou des 'an_'.
Elle se présente de la manière suivante :
[pastacode provider="manual" lang="php"]
class WP_Ajax {
function __construct( $ajax_prefix = 'a', $nopriv_prefix = 'n' ) {
$regex = "/^($ajax_prefix)?($nopriv_prefix)?_|^($nopriv_prefix)?($ajax_prefix)?_/";
$methods = get_class_methods( $this );
foreach ( $methods as $method ) {
if ( preg_match( $regex, $method, $matches ) ) {
if ( count( $matches ) > 1 ) {
$action = preg_replace( $regex, '', $method );
if ( count( $matches ) == 3 ) {
add_action( "wp_ajax_$action", array( $this, $method ) );
add_action( "wp_ajax_nopriv_$action", array( $this, $method ) );
} else {
if ( $matches[1] == $ajax_prefix ) {
add_action( "wp_ajax_$action", array( $this, $method ) );
} else {
add_action( "wp_ajax_nopriv_$action", array( $this, $method ) );
}
}
}
}
}
}
}
[/pastacode]
Si vous voulez faire de l'ajax très rapidement elle est parfaite, elle ajoute automatiquement les différentes actions, mais il faut développer avec des classes.
Bonjour
Tutoriel bien ficelé, j’aurais aimé voir les nonces, tu en parles indirectement en page 5 d’ailleurs mais tu ne les montres pas, ici tu fais un echo de la date donc rien de grave, mais attention aux actions Ajax sans token de sécurité qui sont un vecteur de failles !
Petite rectif, tu écris _( au lieu de __( et tu as déclaré 2 fois a_ajaxLink, le second devant etre an_ajaxLink. Le piège du c/c 😉
Merci Nicolas pour ces tutoriels comme j’aimerai faire si les journées n’avaient pas seulement 24h . . .
Merci! Je vais tâcher de corriger la petite erreur 😉 . Je pense faire un article sur les nonces pour bien saisie les différentes manières de les utiliser 😉 , merci pour ton retour!
Bonjour très bon tuto,
remarque: if( !parent.hasClass(‘ ajaxing’ ) ) { au lieu de if( !parent.haveClass( ajaxing ) ) {
je me suis inspiré du tuto pour faire un plugin pour un projet wordpress. l’ajax marche parfaitement mais j’ai un souci lorsque je reçois un contenu paginé. lorsque je veux parcourir la pgination en ajax également sa ne marche plus.
la pagination généré par ajax posséde l’url …/wp-admin/admin-ajax.php?numéro de la page
un clic execute plutot le lien et non le traitement ajax prévu.
Peux-tu avoir une idée? Merci!
Salut !
Merci pour les remarques, j’ai mis à jour l’article :).
Sinon pour ton problème, j’ai aussi mis à jour l’article pour que ça colle. En gros au lieu d’utiliser .click(), il faut utiliser .on()
jQuery(".parent").on( 'click', '.children', function(){....});
Attention cette fonction n’existe que depuis jQuery 1.8 😉
Merci pour ton aide. sa marche à merveille. quand je pense que depuis hier j’étais dessus et j’ai même fait un post sur le forum.
pour la remarque de tout à l’heure, t’as oublié de mettre ajaxing entre quotte, c’est une chaîne et non une variable.
Merci encore!
Content d’avoir pu aider :D.
Article mis à jour !
Salut,
Tout d’abord merci pour ce bon tuto 😀
Je débute, (je ne suis pas très doué ) et je voudrais rajouter dans la partie admin lorsque l’on crée une page ou un article, en dessous des autres méta box un compteur de mot clé qui utilise de l’ajax. Je récupère mes infos à partir d’un formulaire (un champs pour les mots clés et l’autre champs pour le texte, qui est le texte à traiter)
Je voudrais donc savoir si il était possible d’appliquer ce tuto directement à mon cas .
(je possède déja le code qui fonctionne à part mais je n’arrive pas à l’intégrer sur wordpress par rapport à ajax )
Merci ^^.
Bonjour,
Tout d’abord , très bon tutoriel.
Je ne suis pas très doué (je débute ) et voudrais insérer un compteur de mot clé dans le back office, dans la partie création de page et d’articles.
Je possède déjà un code qui fonctionne à part mais l’intégration au de mon code sur wordpress par rapport à l’ajax.
La base de mon code est un formulaire (un champs pour les mots clés, un autre pour le texte à traiter ).
Penses-tu que cette méthode pourrait fonctionner avec la mienne ?
Merci d’avance
Salut,
Ta méthode peut parfaitement fonctionner, mais si c’est juste compter le nombre de mots-clé dans un champs texte présent dans la de façon dynamique en fonction d’un autre champ actuellement disponible, je pense qu’une solution javascript serait le plus adapté.
Sinon oui tu peux envoyer le texte courant en AJAX à WordPress puis le traiter.
Bonjour,
Est ce qu’un site dont aucun plugin « rating » ne fonctionnent, veut dire que le template ne dispose pas de cette fonction « ajax »? Aucun plugin de notation fonctionne sur mon site .
Merci
C’est possible que l’ajax ne fonctionne pas a cause d’erreurs dans le PHP, tentez de désactiver tous les plugins et mettre un thème de base de WordPress.
Puis d’activer uniquement le plugin de rating, s’il marche alors un de vos plugins pose problème. Réactivez les un par un pour voir lequel pose problème.
Nicolas
En effet! Ca faisait 2 jours que j’étais dessus ! Le plugin qui me faisait défaut était « Scripts-To-Footer » Merci Nicolas 😉 et merci pour ton retour, sympa 😉