Is there anyway to format Phone Numbers and/or Web Address PRIOR to inserting them into the database? For example, let's say a user puts one of the following telephone numbers into the box:

(777) 111-2222
777-111-2222
777.111.2222
7771112222

I would like these to be stored in the database as:

(777) 111-2222

Similarly, with web addresses if the user puts something like:

www.domain.com
domain.com
http://domain.com
http://www.domain.com

I wanted it to be stored in the database as:

http://www.domain.com


Any ideas?

Dani AI

Generated

Brief summary and recommended approach tied to the thread: keep storage canonical and do presentation formatting at render time. For phone numbers the canonical choice is the international E.164 form (digits with a leading +) and display the national/local formatted string when needed. For URLs store a validated, normalized URL with scheme and an ASCII host (IDN → punycode); drop client-only fragments for storage. These choices make searching, comparison and integrations simpler. (itu.int)

On phone handling: 's quick preg_replace trick is fine for simple US-only input, but it breaks on international and tricky edge cases. A robust, production-safe solution is Google’s libphonenumber (PHP ports exist) — it parses, validates and formats to E.164 and national formats. Install with Composer and use the phone util to parse → validate → format (store E.164, keep the formatted national for UI). (github.com)

A compact URL-normalization pipeline (conceptual):

  • ensure a scheme (prepend http:// when absent),
  • validate with FILTER_VALIDATE_URL,
  • parse components with parse_url,
  • convert host to ASCII with idn_to_ascii (if present) and lowercase it,
  • drop the fragment for storage, and decide deliberately whether to force or add “www.” (avoid forcing it blindly).

Example normalization skeleton:

// install intl extension for idn_to_ascii
function normalize_url(string $in): ?string {
  $s = trim($in);
  if (!preg_match('~^[a-z][a-z0-9+.-]*://~i',$s)) $s = 'http://'.$s;
  if (!filter_var($s, FILTER_VALIDATE_URL)) return null;
  $p = parse_url($s);
  $host = strtolower($p['host'] ?? '');
  if (function_exists('idn_to_ascii')) $host = idn_to_ascii($host, IDNA_DEFAULT, INTL_IDNA_VARIANT_UTS46);
  $path = $p['path'] ?? '/';
  $q = isset($p['query']) ? '?'.$p['query'] : '';
  return "{$p['scheme']}://{$host}{$path}{$q}";
}

See PHP docs for filter_var, parse_url and idn_to_ascii. (php.net)

Cautions: keep the original user input for audit, always validate (don’t trust normalization alone), and use prepared statements when saving to the DB. Avoid forcing “www.” unless the application specifically requires that canonical form.

Recommended Answers

All 9 Replies

Use preg_replace() to match and format the values supplied by users.
Strip the phone numbers of any non-numeric characters first. Apply

$number = preg_replace( '/[^0-9]/', '', $number );
$number = preg_replace( '/([0-9]{3})([0-9]{3})([0-9]{4})/', '($1) $2-$3', $number );

Likewise for the domain.

commented: Great informative post! +1

Use preg_replace() to match and format the values supplied by users.
Strip the phone numbers of any non-numeric characters first. Apply

$number = preg_replace( '/[^0-9]/', '', $number );
$number = preg_replace( '/([0-9]{3})([0-9]{3})([0-9]{4})/', '($1) $2-$3', $number );

Likewise for the domain.

Worked perfectly, thanks for the help. Could I also use preg_replace for the web addresses or would that be more difficult considering we don't know how many characters are in the domain name?

Member Avatar for Member #120589

Just a bit of code I had a go at. It's not as clean as preg_replace though. I'm not bright enough to pretend I understand it. The code below works with all the examples in the array.

<?php
$url_array = array('','','www.diafol.org','diafol.org','','','diafol.org/index.php?id=1&id2=678#anchor');
foreach($url_array as $url){
	$host = ""; $path = ""; $query = ""; $fragment = "";
	$parse_url = parse_url($url);
	$schema = (isset($parse_url['scheme'])) ? $parse_url['scheme'] . "://" : "http://";
	if(isset($parse_url['host'])){
		$host = (strpos($parse_url['host'],"www.") !== false) ? $parse_url['host'] : "www." . $parse_url['host'];
	}else{
		$path = (strpos($parse_url['path'],"www.") !== false) ? $parse_url['path'] : "www." . $parse_url['path'];
	}
        if(isset($parse_url['query']))$query = "?" . $parse_url['query'];
	if(isset($parse_url['fragment']))$fragment = "#" . $parse_url['fragment'];
	echo "URL = $url but CODE gives: " . $schema . $host . $path . $query . $fragment . "<br />";
}
?>

You obviously don't need all that:

<?php
        $url = ....;
	//$host = ""; $path = ""; $query = ""; $fragment = ""; don't need
	$parse_url = parse_url($url);
	$schema = (isset($parse_url['scheme'])) ? $parse_url['scheme'] . "://" : "http://";
	if(isset($parse_url['host'])){
		$host = (strpos($parse_url['host'],"www.") !== false) ? $parse_url['host'] : "www." . $parse_url['host'];
	}else{
		$path = (strpos($parse_url['path'],"www.") !== false) ? $parse_url['path'] : "www." . $parse_url['path'];
	}
        if(isset($parse_url['query']))$query = "?" . $parse_url['query'];
	if(isset($parse_url['fragment']))$fragment = "#" . $parse_url['fragment'];
	$standard_url = $schema . $host . $path . $query . $fragment;
?>

Can't help thinking that smant's gonna come back with a two-line snippet that's gonna make me look like a mook. :)

It depends on how regular your input is. In your example, domain names consist of lower-char strings with dots in between with an optional protocol name:

$sample = " 1word www.domain.com no period domain.com period. http://domain.com what else? http://www.domain.com ";
if (preg_match_all( '~([a-z]+://)?(([a-z0-9]+\.)+([a-z]{2}[a-z]?[a-z]?))~', $sample, $matches, PREG_SET_ORDER))
  print_r( $matches );
Array
(
    [0] => Array
        (
            [0] => [url]www.domain.com[/url]
            [1] =>
            [2] => [url]www.domain.com[/url]
            [3] => domain.
            [4] => com
        )

    [1] => Array
        (
            [0] => domain.com
            [1] =>
            [2] => domain.com
            [3] => domain.
            [4] => com
        )

    [2] => Array
        (
            [0] => [url]
            [1] => http://
            [2] => domain.com
            [3] => domain.
            [4] => com
        )

    [3] => Array
        (
            [0] => [url]
            [1] => http://
            [2] => [url]www.domain.com[/url]
            [3] => domain.
            [4] => com
        )

)

// hey ardav, what's a mook?

Member Avatar for Member #120589

Hah, hah hah, I hate you :)

Mook? Dunno - sounds like some flavour of idiot you'd find in a gangster movie. Like I mentioned, I'm not bright enough to understand preg/regex - gives me a nosebleed. Anyway, can your code transform various url formats to jr's standard? I can see that it detects certain parts. I'd use that myself!

Yes, if preg can identify elements it can also transform them to any standard. My code does not provide for some more exotic url forms like username/password elements, and it does not tackle the query string, if present. But with an additional bracket you can at least catch the standard subdomain, domain and top level domain parts:

preg_match_all( '~([a-z]+://)?(([a-z0-9]+\.)?([a-z0-9]+\.)+([a-z]{2}[a-z]?[a-z]?))~', $sample, $matches, PREG_SET_ORDER)

Array
(
    [0] => Array
        (
            [0] => [url]www.domain.com[/url]
            [1] =>
            [2] => [url]www.domain.com[/url]
            [3] => www.
            [4] => domain.
            [5] => com
        )

    [1] => Array
        (
            [0] => domain.com
            [1] =>
            [2] => domain.com
            [3] =>
            [4] => domain.
            [5] => com
        )

    [2] => Array
        (
            [0] => [url]
            [1] => http://
            [2] => domain.com
            [3] =>
            [4] => domain.
            [5] => com
        )

    [3] => Array
        (
            [0] => [url]
            [1] => http://
            [2] => [url]www.domain.com[/url]
            [3] => www.
            [4] => domain.
            [5] => com
        )

)
Member Avatar for Member #120589

AH OK, got you. So you need to mess about with the $matches variable? Would it be possible to do a one-stop shop with something like preg_replace? Just asking out of curiosity more than anything.

Of course. With preg_replace you can synthesize any expressions which you could catch with preg_match. E.g. for formatting domain names, you could use:

echo preg_replace( '~([a-z]+://)?(([a-z0-9]+\.)?([a-z0-9]+\.)+([a-z]{2}[a-z]?[a-z]?))~s', '<a href="">$2</a>', $sample);
//Result: 1word <a href="http://www.domain.com">www.domain.com</a> no period <a href="http://domain.com">domain.com</a> period. <a href="http://domain.com">domain.com</a> what else? <a href="http://www.domain.com">www.domain.com</a>
Member Avatar for Member #120589

THanks smant, after I stem the flow from both nostrils, I shall endeavour to decipher yon perlified gibberish. Perhaps, I will have another crack at regex - but understanding it well may be beyond my genetic potential!

Thanks again.

Be a part of the DaniWeb community

We're a friendly, industry-focused community of developers, IT pros, digital marketers, and technology enthusiasts meeting, networking, learning, and sharing knowledge.