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 e-mail 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.