C'est quelquefois ardu de valider un numéro de téléphone quand il faut prendre en compte les espaces, les éventuels tirets, les indicateurs géographiques, etc. Inutile de s'embarasser d'un enième bundle pour réaliser ça, ou même d'écrire soi-même des expressions régulières pour couvrir toutes les situations. La librairie giggsey/libphonenumber-for-php
est très complète sur la question. Je vais vous montrer comment l'intégrer facilement à un projet Symfony en créant une contrainte de validation personnalisée.
Cette librairie est basée sur la librairie libphonenumber de Google. Pour la télécharger, c'est très simple:
composer require giggsey/libphonenumber-for-php
Nous allons ensuite créer notre contrainte de validation.
<?php
namespace AppBundle\Validator\Constraints;
use Symfony\Component\Validator\Constraint;
/**
* @Annotation
*
*/
class Telephone extends Constraint
{
public $message = "Ce numéro de téléphone n'est pas valide.";
}
Pensez à modifier le namespace pour qu'il corresponde au bundle où vous vous situez. Personnalisez ensuite le message d'erreur pour qu'il corresponde à ce que vous souhaitez valider. Pour ma part, je vais me contenter de valider un numéro de téléphone français, qu'il s'agisse d'un mobile ou d'un fixe.
La validation proprement dite:
<?php
namespace AppBundle\Validator\Constraints;
use Symfony\Component\Validator\Constraint;
use Symfony\Component\Validator\ConstraintValidator;
class TelephoneValidator extends ConstraintValidator
{
public function validate($value, Constraint $constraint) {
$phoneNumberUtil = \libphonenumber\PhoneNumberUtil::getInstance();
try {
$phoneNumberObject = $phoneNumberUtil->parse($value, 'FR');
if ($phoneNumberUtil->isValidNumber($phoneNumberObject) === false ){
return $this->context
->buildViolation($constraint->message)
->addViolation()
;
}
}
catch(\Exception $e){
return $this->context
->buildViolation($constraint->message)
->addViolation()
;
}
}
}
Voilà! C'est à peu près tout ce qu'il faut pour valider un numéro de téléphone français. Je vous montre un exemple d'utilisation pour valider un attribut d'une entité.
<?php
namespace AppBundle\Entity;
use Doctrine\ORM\Mapping as ORM;
use Symfony\Component\Validator\Constraints as Assert;
use AppBundle\Validator\Constraints as AppAssert;
/**
* @ORM\Entity
* @ORM\Table(name="users")
*/
class User extends
{
/**
* @ORM\Id
* @ORM\Column(type="integer")
* @ORM\GeneratedValue(strategy="AUTO")
*/
protected $id;
/**
* @var string
* @ORM\Column(name="telephone", type="string", length=35)
* @Assert\NotBlank()
* @AppAssert\Telephone()
*/
protected $telephone;
/**
* Set telephone
* @param string $telephone
* @return User
*/
public function setTelephone($telephone)
{
$this->telephone = $telephone;
return $this;
}
/**
* Get telephone
*
* @return string
*/
public function getTelephone()
{
return $this->telephone;
}
}
La librairie est très complète et ses possibilités dépassent largement ce tutoriel. Je vous encourage vraiment à consulter la doc pour des choses plus spécifiques. Allez pour le fun, je vais continuer à vous montrer quelques exemples.
<?php
namespace UserBundle\Validator\Constraints;
use Symfony\Component\Validator\Constraint;
use Symfony\Component\Validator\ConstraintValidator;
class TelephoneValidator extends ConstraintValidator
{
public function validate($value, Constraint $constraint)
{
if(empty($value))
{
return;
}
$phoneNumberUtil = \libphonenumber\PhoneNumberUtil::getInstance();
try {
$phoneNumberObject = $phoneNumberUtil->parse($value, 'FR');
if ($phoneNumberUtil->isValidNumber($phoneNumberObject) === false || $phoneNumberUtil->getNumberType($phoneNumberObject) !== 1)
{
return $this->context
->buildViolation($constraint->message)
->addViolation()
;
}
}
catch(\Exception $e){
return $this->context
->buildViolation($constraint->message)
->addViolation()
;
}
}
}
<?php
namespace UserBundle\Validator\Constraints;
use Symfony\Component\Validator\Constraint;
use Symfony\Component\Validator\ConstraintValidator;
class TelephoneValidator extends ConstraintValidator
{
public function validate($value, Constraint $constraint)
{
if(empty($value))
{
return;
}
$phoneNumberUtil = \libphonenumber\PhoneNumberUtil::getInstance();
try {
$phoneNumberObject = $phoneNumberUtil->parse($value, 'FR');
if ($phoneNumberUtil->isValidNumber($phoneNumberObject) === false || $phoneNumberUtil->getNumberType($phoneNumberObject) !== 0)
{
return $this->context
->buildViolation($constraint->message)
->addViolation()
;
}
}
catch(\Exception $e){
return $this->context
->buildViolation($constraint->message)
->addViolation()
;
}
}
}
Pour info, les types de lignes sont listés dans la PhoneNumberType de la librairie libphonenumber-for-php.
Petite astuce pour quiconque habite l'île de la Réunion. J'y ai habité et j'ai dû valider des numéros locaux. La librairie le permet très facilement. Remplacez "FR" par "RE" et le tour est joué.
<?php
// ...
class TelephoneValidator extends ConstraintValidator
{
public function validate($value, Constraint $constraint)
{
// ...
try {
$phoneNumberObject = $phoneNumberUtil->parse($value, 'RE');
}
// ...
}
}