UK telephone number validation regex

Hi Guys!

I have a function which checks to see if a UK telephone number is valid. However, I had a customer register with a 10 digit telephone number and it didn’t work. Does anyone know how to fix so it works with 10 digits?


function ValidateTelephone($string)
	{
		if(preg_match('/^((\\(?0\\d{4}\\)?\\s?\\d{3}\\s?\\d{3})|(\\(?0\\d{3}\\)?\\s?\\d{3}\\s?\\d{4})|(\\(?0\\d{2}\\)?\\s?\\d{4}\\s?\\d{4}))(\\s?\\#(\\d{4}|\\d{3}))?$/', $string))
		{
			return true;
		} else
		{
			return false;
		}
	}

I take it you mean something like (0800) 123 456, where the missing digit is in the area code?

In that case it’d be (shortened that for you):

function ValidateTelephone($string){ 
    return preg_match('/^\\(?0\\d{3,5}\\)?\\s?\\d{3,4}\\s?\\d{3,4}(\\s?\\#(\\d{4}|\\d{3}))?$/', $string) !== false;
}

(Some rare area codes are 6 digits long, including the zero)

Alternatively you can give yourself more flexibility by doing some pre-check replacing:

function ValidateTelephone($string){
    $string = str_replace(array('(', ')', ' '), '', $string);
    return preg_match('/\\d{10,12}\\#?\\d{3,4}?/', $string) !== false;
}

That allows the user to enter in their number with brackets and spaces wherever they want them, and it checks that it’s a 10-12 digit number with a possible 3/4 digit extension.

Working on similar today, as it happens.

I took the view that I’d remove anything not a number and store the digits only.

pros

It reads vastly easier
Output is ready to go to an autodialler in the future
It can handle any local number formatting – not just UK (France for example use groups of two 05 65 23 45 56)

cons

If the user comes back to edit the phone number it is harder to read without the spaces and formatting

But you can always split the numbers up on display if you have to.

Its one of those “it depends” cases, so added my 2c FWIW.

Alternatively, 3 fields (Area code, Number and Extension) could be used?

Hi Guys!

Thanks for the help but the only number that didn’t seem to work is: 01460643xx (left last two numbers off for security). Is there anyway I can change the regex I already had to accomodate numbers in the above format?


if(preg_match('/^((\\(?0\\d{4}\\)?\\s?\\d{3}\\s?\\d{3})|(\\(?0\\d{3}\\)?\\s?\\d{3}\\s?\\d{4})|(\\(?0\\d{2}\\)?\\s?\\d{4}\\s?\\d{4}))(\\s?\\#(\\d{4}|\\d{3}))?$/', $string))
		{
			return true;
		} else
		{
			return false;
		}

Thanks!

Yes, but you’re still limiting yourself by over-complicating it. The only real pattern in UK telephone addresses is that they begin with 0 and have greater than or equal to 10 characters.

So the following should do fine for you, updated from before to include either 0 or +44 at the beginning, but nothing else:


function ValidateTelephone($string){
    $string = str_replace(array('(', ')', ' '), '', $string);
    return preg_match('/(0|\\+44)\\d{9,11}\\#?\\d{3,4}?/', $string) !== false;
}

Otherwise you’re restricting your user input based on the format you want them to input in, which isn’t added security - it’s added complication and annoyance. I’m not going to help you annoy people :stuck_out_tongue:

You could strip out anything that isn’t a number, then:

<?php

// phone number after having beein striped of any non-numeric stuff and spaces

$phone_number = '01234567890';

$phone_length = strlen($phone_number);

$number = substr($phone_number,-6,6);

$phone_code = substr($phone_number,0,($phone_length-6));

echo "<p>Phone Code: $phone_code</p>";

echo "<p>Phone Number: $number</p>";
?>


That will give you the phone code and phone number separately, you then check the phone code against a list of known phone codes (probably stored in a db table). You’ll want to have the +44 in any phone numbers swapped for their normal uk area codes.

Phone codes in the uk http://en.wikipedia.org/wiki/Telephone_numbers_in_the_United_Kingdom if you poke about a bit you could probably get a list from dbpedia …

But with mobile numbers too? like Jake says, starts with 0, x digits long and they are all numbers, store it, move on…

Instead of have one, big, illegible RegExp that may or may not match your desired pattern. Why not normalise the incoming string, then iterate over an array of more focused patterns. You’ll find it much easier to understand and extend.


<?php
foreach($patterns as $pattern){
    if( ! preg_match ... ){
        return false;
    }
}
return true;

The above example assumes you’ll have all your bases covered, but this is easy to invert.