Comment créer un système de templating d’e-mail en PHP ?

Marre d’écrire du code du style $email_html = 'Bonjour ' . $nom . ' ' . $prenom . '...' pour générer les contenus dynamiques de vos e-mails ? Vous aimeriez bien embellir vos e-mails envoyés en PHP avec un template HTML un peu plus sexy mais ne savez pas comment faire ?

Voilà une petite fonction PHP bien pratique qui va nous rendre la vie plus simple pour envoyer des e-mails en PHP ou dans WordPress.

Vous pouvez visualiser ou téléchargez les fichiers ici :
Voir les fichiers sur GitHub : https://gist.github.com/psaikali/d11c7680adfc11c7198e17d4df161d65
Télécharger le ZIP du code de ce tutoriel : http://media.mosaika.fr/joph
Notez que les fichiers sources n’incluent entre autre pas de fichier /emails/logo.png qui s’affichera en en-tête des e-mails envoyés.

Pourquoi des modèles d’e-mails en PHP ?

Si vous avez déjà envoyé des e-mails en PHP ou dans le code de votre thème/plugin WordPress, vous vous êtes peut-être rendu compte que générer le contenu (HTML ou non) du corps de l’e-mail peut s’avérer chaotique. Il suffit d’avoir quelques variables dynamiques à injecter dans le corps de l’e-mail et notre code devient tout de suite difficilement lisible, rempli de concaténations, chaines de caractères, variables, ouvertures et fermetures de tags HTML et j’en passe.

Personnellement, j’en ai vite eu marre d’avoir un ramassis de code tout sale et illisible à chaque fois que j’avais besoin d’envoyer un e-mail dans mes développements de sites WordPress. J’ai donc fouillé un peu notre vaste toile et je suis tombé sur une classe PHP assez simple mais très efficace. Elle va nous permettre de rendre la génération de contenus d’emails bien plus agréable et de garder un code lisible et organisé. Quoi de mieux pour un bon développeur PHP 😉 ?

Ce tutoriel ce base donc sur cette classe PHP légèrement modifiée et va nous permettre d’envoyer par WordPress des e-mails en PHP sur la base d’un modèle (template) dans lequel nous avons placé des {{ placeholder }} (ou tags). Ces tags sont analysés et remplacés par une valeur que nous fournissons dans un tableau initial : {{ prenom }} est remplacé par la valeur de $data[‘prenom’].

Explication concrète de l’usage de notre fonction msk_send_mail() :
<?php

/*
* Usage de la fonction msk_send_mail
*/

$destinataire = 'pierre@mosaika.fr';

$data = array(
	'prenom' => 'Bruce',
	'nom' => 'Willis',
	'email' => 'bruce.willis@laposte.net',
	'url' => 'https://mosaika.fr'
);

$retour = msk_send_mail('template_when_this_happens', $destinataire, $data);

if (isset($retour['error']) && $retour['error'] == 0) {
	// L'e-mail a été envoyé
} else {
	// Erreur, vérifiez $retour['message'] pour en savoir plus
}

Le template template_when_this_happens est défini dans une autre fonction et ressemble à ça :

'template_when_this_happens' => array(
	'subject' => __('Le sujet de l\'email s\'affiche ici', 'mosaika'),
	'content' => __('Bonjour {{ prenom }} {{ nom }} ! Une nouvelle inscription sur notre site a été faite avec l\'e-mail {{ email }}. Pour vous connecter, <a href="{{ url }}">rendez-vous sur cette page</a>.', 'mosaika')
),

Le code d’envoi d’un e-mail est désormais bien plus épuré : on définit un tableau $data contenant les valeurs à remplacer dans le modèle d’e-mail (la clef étant utilisée comme {{ placeholder }} dans le sujet ou le contenu de notre e-mail).

Ensuite, la fonction msk_send_mail() s’occupe :

  1. de transformer les tags par leurs valeurs qu’on aura fournies dans l’array $data,
  2. d’inclure le contenu généré dans un fichier template emails/base.tpl dans lequel est mis en page notre e-mail (avec un header, un footer, des styles CSS, etc.)
  3. d’envoyer le tout via wp_mail()
  4. et de retourner un tableau informant du bon envoi de l’e-mail ou de la présence d’erreurs

La fonction principale : msk_send_mail()

<?php

/**
 * Envoyer un e-mail : on se base sur un template et on remplace des "placeholders" par des variables dynamiques
 */
function msk_send_mail($template = '', $to = '', $data = array()) {
	// Définissez ici les différents modèles d'e-mail à suivre
	$available_templates = array(
		// Le template d'un premier e-mail
		'template_when_this_happens' => array(
			'subject' => __('Le sujet de l\'email s\'affiche ici', 'mosaika'),
			'content' => __('<p>Bonjour {{ prenom }} {{ nom }} !</p><p>Une nouvelle inscription sur notre site a été faite avec l\'e-mail {{ email }}. Pour vous connecter, <a href="{{ url }}">rendez-vous sur cette page</a>.</p>', 'mosaika')
		),

		// Le template d'un autre e-mail
		'another_template_when_that_happens' => array(
			'subject' => __('Le sujet de l\'email s\'affiche ici', 'mosaika'),
			'content' => __('<p>Bonjour {{ prenom }} {{ nom }} !</p><p>Une nouvelle inscription sur notre site a été faite avec l\'e-mail {{ email }}. Pour vous connecter, <a href="{{ url }}">rendez-vous sur cette page</a>.</p>', 'mosaika')
		),
	);

	if ($to == '') {
		$error = 'Erreur d\'envoi d\'un e-mail : destinataire vide.';
	} else if ($template == '') {
		$error = 'Erreur d\'envoi d\'un e-mail : template vide.';
	} else if (!array_key_exists($template, $available_templates)) {
		$error = 'Erreur d\'envoi d\'un e-mail : template inexistant.';
	} else {
		if (!is_array($to)) $to = array($to);
		// Si le site est en développement, on envoie l'e-mail à l'administrateur du site
		if (WP_DEBUG) $to = array(get_option('admin_email'));

		// On récupère le tableau correspondant au template à analyser/transformer
		$template_data = $available_templates[$template];

		$mail_subject_template = $template_data['subject'];
		$mail_content_template = $template_data['content'];

		// On transforme les {{ placeholders }} par les variables fournies dans $data (pour le sujet et le corps du mail)
		// Par exemple, {{ email }} est remplacé par la valeur de $data['email'], {{ prenom }} par la valeur de $data['prenom']
		$mail_subject = msk_transform_vars_to_value($mail_subject_template, $data);
		$mail_content = msk_transform_vars_to_value($mail_content_template, $data);

		// On intègre le corps/contenu de notre e-mail à la place de {{ body }} dans le fichier /emails/base.tpl
		$mail_html = msk_parse_email_body_content_in_template(array('body' => wpautop($mail_content)));

		// On s'assure que l'e-mail envoyé est au format HTML
		$mail_headers = array('Content-Type: text/html; charset=UTF-8');

		// On envoie l'email
		if (!wp_mail($to, $mail_subject, $mail_html, $mail_headers)) {
			$error = 'Erreur durant l\'envoi de l\'e-mail.';
		}

		if ($error) {
			return array('error' => 1, 'message' => $error);
		} else {
			return array('error' => 0);
		}
	}
}

/**
 * Transforme {{ variable }} en sa valeur correspondante dans le tableau fourni
 */
function msk_transform_vars_to_value($template, $vars) {
	$output = $template;

	foreach ($vars as $key => $value) {
		$tag_to_replace = "{{ $key }}";
		$output = str_replace($tag_to_replace, $value, $output);
	}

	return $output;
}

/**
 * Permet de récupérer tout le contenu HTML de l'e-mail à envoyer, avec tous les {{ placeholders }} remplacés par les valeurs fournies
 */
function msk_parse_email_body_content_in_template($data) {
	require_once(get_stylesheet_directory() . '/emails/emailTemplate.php');
	
	$defaults = array(
		'preheader' => 'Cet e-mail vous est envoyé par XYZ. <a href="https://mosaika.fr">Cliquez-ici</a> pour visiter notre site.',
		'logo' => get_stylesheet_directory_uri() . '/emails/logo.png',
		'body' => '',
		'footer' => 'Copyright 2017 XYZ.',
	);

	$tags = wp_parse_args($data, $defaults);

	$email_content = new MailTemplate(get_stylesheet_directory() . '/emails/base.tpl');

	foreach ($tags as $tag_name => $tag_value) {
		$email_content->set($tag_name, $tag_value);
	}

	return $email_content->output();
}

Dans cette fonction, notez l’important tableau $available_templates qui contient les informations des différents modèles de sujets et corps d’e-mails qui sont à notre disposition.

Dans chaque entrée de ce tableau, le sous-tableau contient une valeur subject qui nous permet de définir le template du sujet (titre) de l’e-mail envoyé. La valeur content est quant à elle analysée pour générer le corps de l’e-mail.

Dans ces deux modèles (sujet et corps), chaque {{ tag }} et remplacé par la valeur qu’on fournit dans le tableau $data en deuxième paramètre de msk_send_mail(). {{ nom }} est donc par exemple remplacé par la valeur contenue dans $data[‘nom’].

Vous pouvez évidemment définir autant de modèles nécessaires dans $available_templates : la clef de chaque modèle est utilisée en premier paramètre de msk_send_mail(). Dans notre exemple ci-dessus, on envoie un e-mail basé sur le modèle contenu dans $available_templates[‘template_when_this_happens’].

Cette fonction fait appel à une autre fonction helper : msk_transform_vars_to_value(). C’est elle qui va analyser une chaîne de caractères pour transformer un template rempli de placeholders (tags) par des valeurs fournies.

Bien plus pratique et lisible d’avoir Bonjour {{ prenom }} {{ nom }}... que nos anciens 'Bonjour ' . $prenom . ' ' . $nom . '...', n’est-ce pas ?

Inclure le contenu généré dans un joli modèle HTML d’e-mail

La dernière fonction msk_parse_email_body_content_in_template va se charger d’une autre étape importante : inclure le corps de l’e-mail, que l’on vient de générer, dans un modèle HTML d’e-mail complexe. Ce modèle (ici fourni et inclus dans /emails/base.tpl) va comprendre toute la structure HTML de l’e-mail, ses styles CSS, son header, son footer, etc.

Il contient surtout lui aussi un placeholder : {{ body }} sera remplacé par le corps de l’e-mail fraîchement généré.

A vous de personnaliser /emails/base.tpl comme bon vous semble. Personnellement, j’aime bien utiliser ce Really Simple Responsive HTML Email Template, mais vous trouverez facilement d’autres modèles HTML d’e-mails responsive et jolis sur Google comme htmlemail.io.

Vous remarquerez que cette fonction msk_parse_email_body_content_in_template propose elle-même des {{ tags }} plus généraux qui sont inclus automatiquement dans notre e-mail final :

  • {{ preheader }} s’affiche avant le logo
  • {{ logo }} est l’URL de l’image du logo utilisé en en-tête d’email
  • {{ footer }} est le texte utilisé en pied de page de l’email

Si vous souhaitez modifier une valeur de ces tags généraux, il suffit de les passer dans le paramètre $data de la fonction msk_send_mail(). Tout simplement !

Dans le code complet que vous trouverez ici, quelques fonctions (comme wp_mail ou locate_template) sont propres à WordPress. Vous pouvez très facilement les remplacer pour les utiliser dans un autre système que WordPress (avec mail() par exemple).

Grâce à tout ça, on peut désormais définir une bonne fois pour toute un joli modèle HTML d’e-mail qui sera utilisé à chaque fois par notre code lors de l’envoi d’e-mails.

A bientôt pour la prochaine astuce !


Vous avez aimé cet article ?

Partagez-le sur vos réseaux sociaux en guise de remerciement :)


Laisser un commentaire