2.4Dates, expressions régulières & e-mails
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.
Le saviez-vous ?
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
- Manipulez des dates avec DateTime : créez, formatez pour l'affichage (->format('d/m/Y')), calculez une différence (->diff) ; configurez le fuseau horaire.
- Retenez : stocker les dates au format standard (ISO) et FORMATER seulement à l'affichage (jamais stocker un format localisé).
- Validez avec filter_var (e-mail, URL) plutôt qu'avec une regex maison ; réservez les regex (preg_match) aux motifs spécifiques.
- 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.
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.
✓ 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().
- 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.
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é.
Comment valider un e-mail en PHP ?