UPDATE :
Des librairies disponibles gratuitement sur Github font un travail formidable dans le formatage des numéros, et bien plus encore !
En effet, il est également possible de récupérer le nom de la ville ou encore la timezone par rapport à un numéro.
Voici un exemple de ces librairies : https://github.com/giggsey/libphonenumber-for-php
Ce matin, je devais afficher des numéros de téléphone belges. Je me souvenais que j’avais déjà fait quelques chose de similaire mais plus moyen de retomber dessus, et de toute façon, d’après mes souvenirs, c’était pas génial. J’ai donc commencé par chercher sur le net une solution toute faite afin de ne pas réinventer la roue.
Après être tombé sur quelques solutions pas géniales, j’ai trouvé un commentaire qui en gros disait « ceci pourrait être mieux fait et plus rapide avec une regex » (expression régulière).
OK très bien, commentaire constructif mais mon gars, t’en dis trop ou pas assez ! Je me suis donc mis en quête de cette fameuse regex mais sans succès, j’ai donc décidé de la construire moi-même. Voici le résultat :
/**
* Check if a number is a valid belgian number
*
* @param integer $number
* @return FALSE or type of phone number
*/
if (!function_exists('valid_be_phone_number')) {
function valid_be_phone_number($number) {
$ret = FALSE;
$number = trim($number);
if (substr($number, 0, 1) != '0' &
&
substr($number, 0, 1) != '+') {
$number = '+32' . $number;
}
// Patterns
$pattern = '/^((\+|00)32\s?|0)(\d\s?\d{3}|\d{2}\s?\d{2})(\s?\d{2}){2}$/';
$pattern_mobile = '/^((\+|00)32\s?|0)4(60|[789]\d)(\s?\d{2}){3}$/';
// Matches
if (preg_match($pattern, $number, $matches)) {
$ret = "fixe";
} else if (preg_match($pattern_mobile, $number, $matches)) {
$ret = "mobile";
}
return $ret;
}
}
/**
* Format a number as a belgian phone number
*
* @param integer $number
* @param bool $internationnal : show the number in internationnal format : +32 (0) XX XX XX XX
* @return string : formated phone number or initial string if not a valid format
*/
if (!function_exists('format_be_phone_number')) {
function format_be_phone_number($number, $internationnal = FALSE) {
$number = trim($number);
if (substr($number, 0, 1) != '0') {
if (substr($number, 0, 1) == '+') {
$number = str_replace('+32', '', $number);
}
$number = '0' . $number;
}
$valid_phone_number = valid_be_phone_number($number);
if ($valid_phone_number !== FALSE) {
if ($valid_phone_number == 'mobile') {
$pattern = '/^\s?(\d{4})\s?(\d{2})\s?(\d{2})\s?(\d{2})\s?$/i';
} else {
$pattern = '/^(?|(0[2349])\s?(\d{3})|(\d{3})\s?(\d{2}))\s?(\d{2})\s?(\d{2})$/i';
}
preg_match($pattern, $number, $matches);
if ($internationnal) {
$number = '+32 (0) ' . substr($matches[1], 1) . ' ' . $matches[2] . ' ' . $matches[3] . ' ' . $matches[4];
} else {
$number = $matches[1] . '/' . $matches[2] . '.' . $matches[3] . '.' . $matches[4];
}
}
return $number;
}
}
Quelques explications
De base, la regex n’est pas très compliquée. Le problème survient au niveau des numéros de téléphones fixes. En effet, certains numéros on un préfixe de 3 chiffres (la plupart des villes) mais les grandes villes ont un préfixe de 2 chiffres (Bruxelles [02], Anvers [03], Liège [04], Gand [09] ; voir Wikipedia). Si on ajoute à ça le fait que je voulais avoir la possibilité d’afficher le numéro au format international, je suis tombé sur un petit problème : le nombre de groupe de capture. En effet, ma première regex comptait 8 groupes de captures (ou 6 en simplifiant la regex par la suite), du coup avant de pouvoir afficher le numéro je devais faire des vérifications sur « quels groupes de capture ne sont pas vides ». Ce n’était pas vraiment génial. J’ai pas mal galéré mais l’astuce se trouve finalement dans la syntaxe (?|. Cette syntaxe que je ne connaissais pas du tout, permet de n’avoir qu’une seule référence de capture pour plusieurs groupes. Il n’y a pas vraiment plus d’infos mais vous pouvez toujours aller voir la Doc PHP qui en parle (tout en bas de la page). Dans ma regex, c’est symbolisé par ceci :
(?|(0[2349])\s?(\d{3})|(\d{3})\s?(\d{2}))
Ceci signifie que mes groupes seront soit les ce qui précède | soit ce qui le suit.
- Si mon numéro commence par 02, 03, 04, 09, on aura donc un préfixe de 2 chiffres (groupe $1), suivit d’un nombre à 3 chiffres (groupe $2)
- Sinon, un préfixe à 3 chiffres (groupe $1) suivi d’un nombre à 2 chiffres (groupe $2).
Ok! Intéressant le sujet, je vais l’étudier sérieusement pour obtenir la même chose par rapport mon pays, le Congo Brazzaville
Hey Charles ! Ca va bien ? 🙂
N’hésitez pas à partager votre résultat
Bonjour,
je reçois l’erreur ci-dessous pour le groupe d’instructions
valid_be_phone_number($number)
140 if (substr($number, 0, 1) != ‘0’ &
141 &
142 substr($number, 0, 1) != ‘+’) {
143 $number = ‘+32’ . $number;
144 }
Est_il possible d’expliquer ce que fait ce groupe d’instructions
Merci
Parse error: syntax error, unexpected ‘;’ in C:…test.php on line 140
Hmmm c’est étrange comme erreur, mais d’après le code que vous copiez/collez; vous avez écrit :
!= « 0 » &
&
Vous ne pouvez pas séparer les « && » pareil pour les « || ». Il s’agit de « mots de clés ». && signifie AND et || signifie OR (vous pouvez d’ailleurs écrire « AND » et « OR » à la place de « && » et « || »). Si vous mettez un des 2 caractères à la ligne, l’instruction ne signifie plus rien.
Dites-moi si ceci à résolu votre problème, sinon je me propose de vous aider en contact privé.
c’est un copier collé des lignes 12-16 de l’exemple ci-dessus
& sont peut être transfomés en & ????
Ces lignes peuvent elles s’écrivent comme suit ?
if (substr($number, 0, 1) != ‘0’ and substr($number, 0, 1) != ‘+’)
{$number = ‘+32’ . $number;}
12 if (substr($number, 0, 1) != ‘0’ &
13 &
14 substr($number, 0, 1) != ‘+’) {
15 $number = ‘+32’ . $number;
16 }
effectivement , après avoir exécuté « post comment »
je trouve seulement & au lieu de & amp
& ou & amp; importe peu.
Ce que je voulais dire, c’est que d’après votre copié/collé, vous un & à la ligne 12 et un autre à la ligne 13. Vous ne pouvez pas séparer les 2 é-commerciaux. Ils doivent être l’un à côté de l’autre et sur la même ligne.
Si quelqu’un lit ce post et a besoin de cas non couverts par le package de validation spécifique à la Belgique de PEAR : https://github.com/pear/Validate_BE
N’hésitez pas à le décrire dans https://pear.php.net/bugs/report.php?package=Validate_BE
Même si PEAR semble à l’abandon, ses packages les plus simples restent disponible et fonctionnels
C’est vrai que je n’ai jamais updaté ce post mais je vais le faire.
En effet, il existe de nombres lib disponibles sur github qui couvrent tous les numéros de téléphones du monde et qui permettent même de trouver la ville ou la timezone en fonction du numéro.
Voici un exemple de librairie vraiment utile : https://github.com/giggsey/libphonenumber-for-php