How to validate and sanitize a phone number in symfony

This validator works for symfony 1.4 and is not necessarily backward compatible.

If you’d like to both validate and sanitize a phone number in symfony, it’s pretty easy. First, put the following code in lib/myValidatorPhone.class.php:

<?php
 
/**
 * myValidatorPhone validates a phone number.
 *
 * @author Jason Swett (http://jasonswett.net/how-to-validate-and-sanitize-a-phone-number-in-symfony/)
 */
class myValidatorPhone extends sfValidatorBase
{
  protected function doClean($value)
  {
    $clean = (string) $value;
 
    $phone_number_pattern = '/^(^(1\s*[-\/\.]?)?(\((\d{3})\)|(\d{3}))\s*[-\/\.]?\s*(\d{3})\s*[-\/\.]?\s*(\d{4})\s*(([xX]|[eE][xX][tT])\.?\s*(\d+))*$)*$/';
 
    if (!$clean && $this->options['required'])
    {
      throw new sfValidatorError($this, 'required');
    }
 
    // If the value isn't a phone number, throw an error.
    if (!preg_match($phone_number_pattern, $clean))
    {
      throw new sfValidatorError($this, 'invalid', array('value' => $value));
    }
 
    // Take out anything that's not a number.
    $clean = preg_replace('/[^0-9]/', '', $clean);
 
    // Split the phone number into its three parts.
    $first_part = substr($clean, 0, 3);
    $second_part = substr($clean, 3, 3);
    $third_part = substr($clean, 6, 4);
 
    // Format the phone number.
    $clean = '('.$first_part.') '.$second_part.'-'.$third_part;
 
    return $clean;
  }
}

Then, in the form where you have your phone number field, add the following line to your configure() method:

$this->validatorSchema['phone'] = new myValidatorPhone(array('required' => false));

That’s all! Now, if someone enters a number like 123.456.7890, it will get saved as (123) 456-7890.

3 Responses to “How to validate and sanitize a phone number in symfony”

  1. Richard says:

    Thanks for the validator. BTW, the @author link in your code returns 404

  2. jason says:

    Glad you found it useful, and thanks for pointing out that mistake. I’ve fixed it.

  3. Evan Muller says:

    Thanks for the validator! But there’s a bug, your regex allows for a leading 1 as in “1 (123) 123-1234″ this would get converted to “(112) 312-3123″. I created this regex instead: ‘/^(\((\d{3})\)|(\d{3}))\s*[-\.]?\s*(\d{3})\s*[-\.]?\s*(\d{4})$/’, it doesn’t allow for the leading 1, doesn’t allow for / separators, there must actually be a phone number, and there can’t be an extension.