Catégories
Blog DĂ©veloppement

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 :

add_action( 'wp_ajax_getPost', 'get_the_posts' );

ou

add_action( 'wp_ajax_nopriv_getPost' , 'get_the_posts' );

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’.

add_filter( 'the_content', 'add_content_ajax_link' );

function add_content_ajax_link( $content ) {
	$content .= '</pre>
<div class="ajax_link_wrapper"><a class="ajax_link" href="#">'.__( 'Give me more !').'</a></div>
<pre>
';
	return $content;

}

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.

// 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();
}

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:

// 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' )  )  );

}

La fonction wp_enqueue_script accepte 5 paramĂštres:

  1.  l'identifiant unique du script pour WordPress
  2. L'url du script Ă  importer
  3. La dépendance du script, ici il faut jQuery pour que ça marche car nous allons utiliser le jquery de WordPress
  4. La version de notre script ( utile pour le cache en cas de mise Ă  jour )
  5. 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.
Nous avons donc ajouté un script qui se site dans le dossier js de votre thÚme sous le nom ajax_link.js.
La fonction wp_localize_script accepte 3 paramĂštres :
  1. L'identifiant du script qui utilise la variable
  2. Le nom de la variable javascript qui sera créée
  3. Un tableau de clé/valeurs qui vous permettent de passer des variables PHP trÚs facilement, ou des chaßnes traduites !
Nous avons donc dans notre source html une variable javascript qui porte le nom aLink et qui a un index ajaxurl qui contient l'url vers l'API de l'ajax.
Attaquons nous au Javascript !

Le 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 );
				}
			} );
		}
	});
});

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

add_filter( 'the_content', 'add_content_ajax_link' );
function add_content_ajax_link( $content ) {
	$content .= '</pre>
<div class="ajax_link_wrapper"><a class="ajax_link" href="#">'.__( 'Give me more !').'</a></div>
<pre>
';
	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' )  )  );
}

Le 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 );
				}
			} );
		}
	});
});

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 :

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 ) );
                                                }
                                        }
                                }
                        }
                }
        }
}

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.

12 réponses sur « Bonnes pratiques : AJAX et WordPress »

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!

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 😉

Laisser un commentaire

Votre adresse de messagerie ne sera pas publiée. Les champs obligatoires sont indiqués avec *

Ce site utilise Akismet pour réduire les indésirables. En savoir plus sur comment les données de vos commentaires sont utilisées.