Je vais maintenant aborder un aspect important dans tout bon projet Web : L’envoi de mails.
Tout site internet a, dans 90% des cas (pour ma part) besoin d’envoyer des mails automatiques :
- confirmation d’inscription
- mot de passe oublié
- notifications pour messages reçus
- etc…
Pour mes projets, j’avais plusieurs besoins (ou envies
)
- un jolie template de mail (c’est toujours agréable de recevoir un jolie mail)
- véhiculer l’information principale de ce mail
- apporter des informations dynamique pour donner vie au mail.
Avec Symfony 1.3 & 1.4, l’envoi de mail a été simplifié grâce à l’apparition de SfMailer. Mais, je voulais aller plus loin, en utilisant le même modèle Symfony -> actions/templates/partials/composants pour les contenus de mail.
Je vais vous présenter cela par un exemple concret : Une confirmation d’inscription.
1. Problématique
Suite à une inscription sur votre site Internet, vous désirez envoyer un email de remerciement accompagné des derniers membres inscris et la dernière news rédigée.
2. Le template de mail
Créer un fichier apps/frontend/templates/layout_mail.php avec dedans le contenu de votre template :
<html>
<head>...</head>
<body>
<div class='header'> ... Votre haut de mail </div>
<div class='content'> <?php echo $sf_content ?> </div>
<div class='footer'> ... Votre pied de mail </div>
</body>
</html>
3. Centralisation des emails
L’idée est de centraliser dans un module tous les différents mails envoyés automatiquement depuis le site Internet. Créer un module mail :
symfony generate:module frontend mail
Editer le fichier actions.class.php de ce module pour rajouter l’action pour l’email d’inscription :
<?php
class mailActions extends sfActions
{
public function preExecute()
{
//On précise ici que tous les mails utiliseront le layout que nous avons spécialement défini pour cela
$this->setLayout('layout_mail');
}
public function executeInscription(sfWebRequest $request)
{
$this->member = Doctrine::getTable('member')->find($request->getParameter('id'));
}
}
4. Dynamisation des mails grâce aux components
Créer le fichier components.class.php dans le module mail :
<?php
class mailComponents extends sfComponents
{
public function executeLastMembers()
{
$this->members = Doctrine::getTable('member')->getLast();
}
public function executeLastNews()
{
$this->news = Doctrine::getTable('news')->getLast();
}
}
Créer ensuite les deux templates pour ces components : _lastMembers.php et _lastNews.php avec dedans l’affichage des derniers membres et de la dernière news comme vous le souhaitez.
5. Le template pour le mail d’inscription
Créer le fichier inscriptionSuccess.php dans le dossier templates du module mail :
<div>
<?php echo $member->getFullName() ?>, nous vous remercions pour votre inscription sur www.iw2.fr.
</div>
<!-- Nous incluons ici les deux components pour afficher les derniers membres et la dernière news -->
<?php include_component('mail', 'lastMembers')?>
<?php include_component('mail', 'lastNews')?>
6. Une classe mailer pour l’envoi des mails
Cette classe se compose de deux méthodes: une pour centraliser les sujets de mails et l’autre pour l’envoi. Créer un fichier mailer.class.php dans le dossier lib.
class mailer
{
static public function getSubject($action)
{
$subject = array();
$subject['inscription'] = "Confirmation de votre inscription";
//$subject['nom_de_l'action_du_module_mail'] = "Le sujet de ce mail";
return $subject[$action];
}
static public function send ($dest, $action)
{
//En premier paramètre nous avons l'adresse mail du destinataire ou un tableau d'emails. En second paramètre nous avons le nom de l'action du module mail
//On initialise l'objet mailer avec le destinataire et le sujet.
$mailer = sfContext::getInstance()->getMailer()->compose(
null,
$dest,
mailer::getSubject($action)
);
//On initialise le FROM avec des valeurs définie dans le app.yml par exemple
$mailer->setFrom(sfConfig::get('app_mailer_from'), sfConfig::get('app_mailer_name'));
//On précise un rendu de type html
$mailer->setContentType("text/html");
//On rajoute le contenu du mail en récupérant le rendu de l'action du module mail
$mailer->setBody(sfContext::getInstance()->getController()->getPresentationFor('mail', $action));
//On envoi le mail
sfContext::getInstance()->getMailer()->send($mailer);
}
}
Penser à faire un symfony cc à ce niveau pour prendre en compte cette nouvelle classe.
7. Au niveau de l’action d’inscription
Dans votre action qui enregistre l’inscription, exemple :
public function executeCreate(sfWebRequest $request)
{
$this->form = new memberForm();
if( $request->isMethod('post') )
{
$this->form->bind($request->getParameter( $this->form->getName() ), $request->getFiles($this->form->getName()));
if($this->form->isValid()) {
$member = $this->form->save();
//On passe un paramètre à l'objet Request pour le récupérer au niveau de l'action du module mail
$this->getRequest()->setParameter('id', $member->getId());
//On envoi le mail
mailer::send($pro->getEmail(), 'inscription');
$this->redirect('page/remerciement');
}
}
}
8. Exemple de rendu
9. Conclusion
N’ayant rien trouvé sur internet pour répondre à mes besoins en matière d’envoi de mail « dynamique », j’ai décidé de partager avec vous ma solution. Je conçois que celle-ci ne répond peut être pas à tous les critères de BEST PRACTICES Symfony pour le moment, mais c’est une première ébauche qui remplie 100% son rôle. N’hésitez pas si vous avez des questions ou des commentaires.
To be continued…
