2.4 · Dates, expressions régulières & e-mails

Niveau 2 · PHP & le Web

2.4Dates, expressions régulières & e-mails

Objectif : Manipuler les dates avec DateTime (fuseau, format de stockage), valider avec filter_var (plutôt que des regex maison) et envoyer des e-mails via des bibliothèques dédiées — en s'appuyant sur les outils éprouvés.
Temps estimé : 11 min · lecture autonome · Si vous n'avez que 5 min : lisez « L'essentiel en 30s » + le schéma.

L'essentiel en 30 secondes

  • Dates avec DateTime : créer, formater à l'affichage (->format), calculer des écarts (->diff) — fuseau configuré sinon heures fausses.
  • Stocker ISO, afficher local : on stocke AAAA-MM-JJ (triable, non ambigu) et on formate seulement à l'affichage — jamais de format localisé en base.
  • filter_var d'abord, regex si besoin, bibliothèque pour les e-mails : e-mail et URL via filter_var, motifs métier en regex testée, envois via PHPMailer ou Symfony Mailer — jamais mail() en production sérieuse.

Mini-cas filé — Riad date, contrôle et écrit aux adhérents

Dernier acte du chantier : Riad horodate les inscriptions (2.1) et les photos (2.3) avec DateTime — après avoir perdu une après-midi sur des heures décalées à cause du fuseau non configuré. Il contrôle les numéros d'adhérents (format interne précis) avec une regex testée, mais valide les e-mails avec filter_var plutôt qu'une regex maison. Et pour la lettre d'information, il abandonne mail() pour une bibliothèque dédiée qui gère l'authentification et la délivrabilité. Le chantier du niveau 2 est livré : formulaires, sessions, fichiers, dates.

Épilogue du fil rouge 2.1-2.3 : le site de Riad manipule dates, motifs et e-mails avec les bons outils.

1. Dates : DateTime, fuseau et stockage

Les dates sont omniprésentes (création, événements, durées) et PHP moderne les gère en ORIENTÉ OBJET avec DateTime — et DateTimeImmutable, préférable car non modifiable : créer (new DateTime('2026-07-25'), new DateTime() pour maintenant), FORMATER pour l'affichage (->format('d/m/Y')), calculer des DIFFÉRENCES (->diff() entre deux dates, qui gère années bissextiles et mois inégaux), ajouter/soustraire des durées. Les fonctions procédurales anciennes (date(), time(), strtotime()) existent — vous les rencontrerez. Deux vigilances : le fuseau horaire (à configurer explicitement, sinon toutes les heures sont décalées — le piège n°1 de Riad ; pour l'international, stocker en UTC et convertir à l'affichage) et le format de stockage : on stocke au format standard ISO (AAAA-MM-JJ, aussi celui des bases — triable, non ambigu) et on FORMATE seulement à l'affichage — jamais l'inverse.

2. Regex : puissantes, mais pas pour tout

Les expressions régulières (regex) décrivent des MOTIFS dans du texte : vérifier un format (code postal, référence métier), extraire des parties, remplacer selon un motif. En PHP : preg_match() (correspond-il ?), preg_match_all(), preg_replace(), preg_split(). Elles sont PUISSANTES mais réputées difficiles (syntaxe cryptique, faciles à mal écrire — trop strictes, trop laxistes, parfois lentes). D'où la règle : pour les validations COURANTES (e-mail, URL, IP, entier), n'écrivez PAS votre regex — utilisez filter_var() (FILTER_VALIDATE_EMAIL, FILTER_VALIDATE_URL), éprouvé et fiable (valider un e-mail correctement par regex est étonnamment difficile). Réservez les regex aux motifs SPÉCIFIQUES non couverts par les filtres — comme le numéro d'adhérent de Riad — en les testant soigneusement et en les commentant. Pour les manipulations SIMPLES (chercher, remplacer, découper), préférez les fonctions de chaînes, plus lisibles et plus rapides.

3. E-mails : bibliothèque dédiée, en-têtes verrouillés

La fonction native mail() est BASIQUE et peu fiable (délivrabilité, spam, configuration serveur) : pour envoyer sérieusement, on utilise des BIBLIOTHÈQUES dédiées (PHPMailer, Symfony Mailer) qui gèrent l'authentification SMTP, les pièces jointes, le HTML et la délivrabilité — ou des services d'envoi tiers. Point de SÉCURITÉ : ne jamais insérer de données utilisateur non contrôlées dans les EN-TÊTES d'un e-mail (faille d'injection d'en-tête). La lettre d'information de Riad part donc via une bibliothèque, avec des en-têtes construits à partir de valeurs contrôlées. Principe transversal de la section : s'appuyer sur les OUTILS ÉPROUVÉS (DateTime, filter_var, bibliothèques d'e-mail) plutôt que tout bricoler à la main.

Erreur d'interprétation fréquente : « Une regex maison pour les e-mails, c'est plus précis que filter_var ». Non, c'est l'inverse : la spécification des e-mails valides est d'une complexité redoutable, et les regex maison sont presque toujours soit trop strictes (elles rejettent des e-mails valides), soit trop laxistes (elles acceptent n'importe quoi) — sans parler des cas limites jamais testés. filter_var avec FILTER_VALIDATE_EMAIL applique une validation éprouvée et maintenue. La règle de Riad : cas courant couvert par un filtre = filter_var, sans discuter ; regex réservée aux motifs spécifiques à son besoin, testée et commentée.
Dates, motifs, e-mails Les bons outils éprouvés DateTimeCréer, formater, ->diff ; fuseau + ISO+Regex vs filter_varfilter_var pour email/URL ; regex = motifs spécifiques+E-mailsBibliothèque dédiée (pas mail()) S'appuyer sur les outils éprouvés plutôt que tout faire à la main.
Les bons outils éprouvés
Version texte du schéma (SEO / lecteurs d'écran / traduction) : 1) Riad manipule les DATES avec DateTime : création, formatage à l'affichage, écarts avec ->diff — fuseau configuré, stockage en ISO, jamais de format localisé en base. 2) Pour les MOTIFS, il valide e-mails et URL avec filter_var (éprouvé) et réserve les regex testées aux formats métier spécifiques. 3) Il envoie ses E-MAILS via une bibliothèque dédiée (authentification, délivrabilité), sans donnée non contrôlée dans les en-têtes. Leçon : le bon outil éprouvé pour chaque besoin, pas de bricolage maison.

Le saviez-vous ?

Riad a perdu une après-midi sur des heures décalées : le fuseau du serveur n'était pas celui de Constantine.
Vrai : un fuseau non configuré fausse tous les horodatages — le piège n°1 des dates.

Une ligne de fuseau vaut une après-midi de débogage.

🔎 Exemple concret — 🔎 Exemple concret — L'inscription de Riad, datée et validée

DateTime + filter_var, comme chez Riad :

$d = new DateTime('2026-07-25');
echo $d->format('d/m/Y');
// stockage : format ISO 2026-07-25
if (filter_var($email, FILTER_VALIDATE_EMAIL)) {
  echo htmlspecialchars($email, ENT_QUOTES, 'UTF-8');
}

Lecture : création et formatage de date, stockage ISO, validation fiable sans regex maison.

Leçon : configurer le fuseau ; stocker ISO, formater à l'affichage.

Vocabulaire de la section

Dates (DateTime)
PHP moderne manipule les dates avec DateTime/DateTimeImmutable : créer, FORMATER pour l'affichage (->format), calculer des différences (->diff), ajouter/soustraire.

Exemple simple : Riad horodate chaque inscription avec new DateTime().

Ce que ce n'est pas : des calculs de durée à la main sur des timestamps.

Réflexe : manipuler une date = DateTime.

Fuseau & format de stockage
Configurer le FUSEAU horaire (sinon heures fausses) ; STOCKER au format standard ISO (AAAA-MM-JJ) et FORMATER seulement à l'affichage.

Exemple simple : Riad stocke 2026-07-25 et affiche 25/07/2026.

Ce que ce n'est pas : une date localisée stockée telle quelle en base.

Réflexe : stocker ISO, afficher local.

Expressions régulières (regex)
Mini-langage décrivant des motifs dans du texte ; preg_match (correspond ?), preg_replace (remplacer) — puissantes mais difficiles.

Exemple simple : Riad contrôle le numéro d'adhérent avec une regex testée.

Ce que ce n'est pas : une regex maison pour valider les e-mails.

Réflexe : motif métier spécifique = regex testée et commentée.

filter_var pour valider
Pour les validations courantes (e-mail, URL…), préférer filter_var (FILTER_VALIDATE_EMAIL…) à une regex maison — plus fiable.

Exemple simple : Chaque e-mail d'adhérent passe par FILTER_VALIDATE_EMAIL.

Ce que ce n'est pas : une regex copiée sans test pour les e-mails.

Réflexe : cas courant = filtre éprouvé.

Envoi d'e-mails
La fonction native mail() est basique et peu fiable ; utiliser des bibliothèques dédiées (PHPMailer, Symfony Mailer) — jamais de données non contrôlées dans les en-têtes.

Exemple simple : La lettre de Riad part via une bibliothèque avec SMTP authentifié.

Ce que ce n'est pas : un mail() artisanal pour des envois en masse.

Réflexe : e-mail sérieux = bibliothèque dédiée.

En pratique — En pratique — Dates, regex et e-mails

  1. Manipulez des dates avec DateTime : créez, formatez pour l'affichage (->format('d/m/Y')), calculez une différence (->diff) ; configurez le fuseau horaire.
  2. Retenez : stocker les dates au format standard (ISO) et FORMATER seulement à l'affichage (jamais stocker un format localisé).
  3. Validez avec filter_var (e-mail, URL) plutôt qu'avec une regex maison ; réservez les regex (preg_match) aux motifs spécifiques.
  4. Pour envoyer un e-mail sérieusement, utilisez une bibliothèque dédiée (PHPMailer / Symfony Mailer) plutôt que mail() ; n'injectez jamais de données non contrôlées dans les en-têtes.
Vous manipulez les dates avec DateTime (fuseau, format de stockage), validez avec filter_var (plutôt que des regex maison) et envoyez des e-mails via des bibliothèques dédiées — en vous appuyant sur les outils éprouvés.

Script prêt à dire — défendre les outils éprouvés en revue de code (30 s)

« Pour les dates j'utilise DateTime avec le fuseau configuré, je stocke en ISO et je formate à l'affichage — fini les heures décalées. Les e-mails passent par filter_var, pas par une regex maison. Et les envois partent via une bibliothèque avec SMTP authentifié, pas par mail(). Trois outils éprouvés, zéro bricolage. »

À dire en montrant le bug de fuseau corrigé et une regex maison remplacée par filter_var.

Modèle copier-coller — date, écart et validation e-mail

format('d/m/Y');
$aujourdhui = new DateTime();
$ecart = $inscription->diff($aujourdhui);
echo $ecart->format('%a jours d\u2019ancienneté');
// stockage : $inscription->format('Y-m-d H:i:s')
if (!filter_var($email, FILTER_VALIDATE_EMAIL)) {
  echo 'E-mail invalide.';
}

Ancienneté d'adhérent

Riad calcule les années d'adhésion avec ->diff : bissextiles et mois inégaux gérés, sans calcul manuel.

Référence métier

Le numéro d'adhérent suit un format interne strict : regex dédiée, testée sur des cas limites, commentée.

E-mail de bienvenue

Adresse validée par filter_var, envoi via bibliothèque SMTP : la bienvenue arrive au lieu de finir en spam.

Ancien code procédural

Un date() ou strtotime() croisé en maintenance : Riad le lit, puis migre vers DateTime pour toute manipulation.

Prudence : N'insérez jamais de donnée utilisateur non contrôlée dans les en-têtes d'un e-mail : un attaquant y injecte ses propres en-têtes (destinataires cachés, contenu forgé) et détourne votre serveur pour du spam. Construisez les en-têtes à partir de valeurs contrôlées et passez par une bibliothèque qui les protège. Ce guide donne le principe — faites valider tout envoi réel avant la mise en production.

✓ Bonnes pratiques

  • Utiliser DateTime/DateTimeImmutable ; configurer le fuseau horaire.
  • Stocker les dates en ISO, formater seulement à l'affichage.
  • Valider e-mail/URL avec filter_var ; envoyer les e-mails via une bibliothèque dédiée.

✗ Pièges fréquents

  • Fuseau horaire non configuré (heures décalées) — piège n°1.
  • Stocker une date au format localisé (ambigu, non triable).
  • Écrire une regex maison pour valider un e-mail (difficile, peu fiable).

Points clés à retenir

  • DATES : PHP moderne utilise la classe DateTime/DateTimeImmutable (créer, ->format pour l'affichage, ->diff pour les différences). Vigilance : FUSEAU horaire (sinon heures fausses) et FORMAT de STOCKAGE (ISO AAAA-MM-JJ, formater seulement à l'affichage).
  • REGEX (preg_match, preg_replace) = motifs dans du texte, puissantes mais difficiles. Pour les validations COURANTES (e-mail, URL), préférer filter_var (FILTER_VALIDATE_EMAIL) à une regex maison.
  • E-MAILS : la fonction native mail() est basique/peu fiable ; utiliser des BIBLIOTHÈQUES dédiées (PHPMailer, Symfony Mailer) pour la fiabilité et la délivrabilité.
  • Principe transversal : s'appuyer sur les OUTILS ÉPROUVÉS (DateTime, filter_var, bibliothèques d'e-mail) plutôt que tout faire à la main. Sécurité : pas de données non contrôlées dans les en-têtes d'e-mail.

Défi 48h — appliquez demain

Horodatez une vraie donnée avec DateTime (fuseau configuré, stockage ISO, affichage formaté, un ->diff réel), remplacez une regex maison d'e-mail par filter_var, et préparez un envoi via bibliothèque au lieu de mail().

Checklist sortie de section
  • Je peux manipuler une date (créer, formater, calculer un écart) sans erreur de fuseau.
  • Je sais quand utiliser filter_var et quand une regex est justifiée.
  • J'ai préparé un envoi d'e-mail via bibliothèque, en-têtes verrouillés.
Auto-évaluation 1-5 : est-ce que je stocke ISO et formate à l'affichage ?est-ce que je choisis l'outil éprouvé plutôt que le bricolage maison ?

Questions fréquentes

Quels sont les pièges courants avec les dates en PHP, et comment les éviter ?

(1) FUSEAU HORAIRE mal configuré (piège n°1) : heures décalées, horodatages faux. Configurez-le explicitement (date_default_timezone_set() ou date.timezone) ; pour l'international, stockez en UTC et convertissez à l'affichage. (2) Confondre STOCKAGE et AFFICHAGE : ne stockez jamais un format localisé — stockez en ISO (AAAA-MM-JJ, triable, non ambigu, standard en base) et formatez SEULEMENT à l'affichage (->format('d/m/Y')). (3) Anciennes fonctions (date(), strtotime()) : préférez DateTime/DateTimeImmutable pour les manipulations. (4) Calculs manuels (timestamps soustraits) : piégeux (bissextiles, mois inégaux) — utilisez ->diff(). (5) Changement d'heure : DateTime avec les bons fuseaux le gère. (6) Parsing : DateTime::createFromFormat() avec format précis, puis validation.

Faut-il apprendre les expressions régulières, et quand les utiliser (ou les éviter) ?

Oui, les BASES — vous en rencontrerez partout — mais sans obsession. À ÉVITER : (1) validations COURANTES (e-mail, URL, IP, entier) — utilisez filter_var (FILTER_VALIDATE_EMAIL…) : valider un e-mail par regex est étonnamment difficile, les regex maison sont trop strictes ou trop laxistes ; (2) manipulations SIMPLES — préférez les fonctions de chaînes (str_contains, str_replace, explode). JUSTIFIÉES : motifs SPÉCIFIQUES non couverts (format interne, référence métier, extraction précise) — testées soigneusement (cas limites) et COMMENTÉES (illisibles sinon). Le bon développeur sait quand employer une regex et quand préférer l'outil dédié — pas de regex partout par virtuosité.

Vérifiez votre compréhension

Comment valider un e-mail en PHP ?

Ressources supplémentaires (optionnel, pour aller plus loin)

Examen du niveau 2Questions inédites et durcies pour valider vos acquis