Link to home
Start Free TrialLog in
Avatar of skij
skijFlag for Canada

asked on

PHP: Test if string contains only numbers, dashes, parentheses and spaces

Using PHP, how cant I test if string contains only numbers, dashes, parentheses and spaces? If it contains anything else, like a letter, it should return false.
ASKER CERTIFIED SOLUTION
Avatar of Dave Baldwin
Dave Baldwin
Flag of United States of America image

Link to home
membership
This solution is only available to members.
To access this solution, you must be a member of Experts Exchange.
Start Free Trial
Here is a way to annotate the solution with comments and show how to test it.
http://iconoun.com/demo/temp_skij.php
<?php // demo/temp_skij.php

/**
 * http://www.experts-exchange.com/questions/28719388/PHP-Test-if-string-contains-only-numbers-dashes-parentheses-and-spaces.html
 *
 * http://php.net/manual/en/function.preg-match.php
 */
error_reporting(E_ALL);
echo '<pre>';

// A FILTER FUNCTION
function skij_filter($str)
{
    // A REGEX FOR THE EXPECTED FILTERS
    $rgx
    = '/'     // REGEX DELIMITER
    . '['     // START OF CHARACTER CLASS
    . '^'     // NEGATION - MATCH NONE OF THESE
    . '0-9'   // RANGE OF NUMBERS
    . '-'     // THE DASH
    . '()'    // THE PARENTHESES
    . ' '     // THE BLANK
    . ']'     // ENDOF CHARACTER CLASS
    . '/'     // REGEX DELIMITER
    ;
    // TEST FOR A NEGATIVE OF A NEGATIVE CONDITION (!)
    if (!preg_match($rgx, $str)) return TRUE;
    return FALSE;
}

// MAYBE A TELEPHONE NUMBER?  SOME TEST CASES
$tests =
[ '123'
, '(301) 555-1212'
, 'crump'
, '11111111111111111111111111111111111111111111111111111'
, '999-999-9999'
, '((((((((((((((()'
, '--------------'
, '-99993'
, '1-800-BIG-DOGS'
]
;

// RUN THE TESTS AND SHOW THE RESULTS
foreach ($tests as $str)
{
    echo PHP_EOL;
    if ( skij_filter($str) )
    {
        echo ' OK: ';
    }
    else
    {
        echo 'NOK: ';
    }
    echo $str;
}

Open in new window

On the chance that you're looking for phone number authentication, there is a well-understood design pattern ;-)
<?php // demo/validate_phone_numbers.php

/**
 * A function to validate a USA phone number and return a normalized string
 *
 * MAN PAGE: http://discuss.fogcreek.com/joelonsoftware3/default.asp?cmd=show&ixPost=102667&ixReplies=15
 * MAN PAGE: http://www.nanpa.com/number_resource_info/index.html
 */
error_reporting(E_ALL);


function strtophone($phone, $format=FALSE, $letters=FALSE, $dlm='-')
{
    if ($letters)
    {
        // TURN INPUT LIKE 1-800-BIG-DOGS
        // INTO INPUT LIKE 1-800-244-3647
        $phone = strtoupper($phone);
        if (preg_match('/[A-Z]/', $phone))
        {
            $phone = strtr
            ( $phone
            , 'ABCDEFGHIJKLMNOPQRSTUVWXYZ'
            , '22233344455566677778889999'
            )
            ;
        }
    }

    // DISCARD NON-NUMERIC CHARACTERS
    $phone = preg_replace('/[^0-9]/', NULL, $phone);

    // DISCARD A LEADING '1' FROM NUMBERS ENTERED LIKE 1-800-555-1212
    if (substr($phone,0,1) == '1') $phone = substr($phone,1);

    // IF LESS THAN TEN DIGITS, IT IS INVALID
    if (strlen($phone) < 10) return FALSE;

    // IF IT STARTS WITH '0' OR '1' IT IS INVALID, SECOND DIGIT CANNOT BE '9' (YET)
    if (substr($phone,0,1) == '0') return FALSE;
    if (substr($phone,0,1) == '1') return FALSE;
    if (substr($phone,1,1) == '9') return FALSE;

    // ISOLATE THE COMPONENTS OF THE PHONE NUMBER
    $ac = substr($phone,0,3); // AREA
    $ex = substr($phone,3,3); // EXCHANGE
    $nm = substr($phone,6,4); // NUMBER
    $xt = substr($phone,10);  // EXTENSION

    // ADD OTHER TESTS HERE AS MAY BE NEEDED - THESE ARE FOR LOCAL APPS
    if ($ac == '900') return FALSE;
    if ($ac == '976') return FALSE;
    if ($ex == '555') return FALSE;

    // IF NOT FORMATTED
    if (!$format) return $phone;

    // STANDARDIZE THE PRINTABLE FORMAT OF THE PHONE NUMBER LIKE 212-555-1212-1234
    $formatted_phone = $ac . $dlm . $ex . $dlm . $nm;
    if ($xt != '') $formatted_phone .= $dlm . $xt;
    return $formatted_phone;
}



// DEMONSTRATION OF THE FUNCTION IN ACTION.
if (!empty($_GET["p"]))
{
    // VALIDATE PHONE USING FUNCTION ABOVE
    if (!$phone = strtophone($_GET["p"], TRUE))
    {
        // FUNCTION RETURNS FALSE IF PHONE NUMBER IS UNUSABLE
        echo "BOGUS: {$_GET["p"]} ";
    }
    else
    {
        // SHOW THE FORMATTED PHONE
        echo "VALID: {$_GET["p"]} == $phone";
    }
}


// PUT UP A FORM TO TEST PHONE NUMBERS
function ph($p)
{
    echo "<br/><a href=\"{$_SERVER['PHP_SELF']}?p=" . urlencode($p) . "\">$p</a>" . PHP_EOL;
}

$form = <<<EOD
<form>
ENTER A PHONE NUMBER:
<input name="p" /><br/>
<input type="submit" />
</form>
TRY SOME OF THESE (CLICK OR COPY AND PASTE):
EOD;

echo $form;

ph('1-800-5551212');
ph('202-537-7560');
ph('202 537 7560');
ph('1-202-537-7560');
ph('(202) 537-7560');
ph('1.202.537.7560');
ph('123456789');
ph('703-356-5300 x2048');
ph('(212) 555-1212');
ph('1 + (212) 555-1212');
ph('1 (292) 226-7000');

Open in new window

@skij (and anyone else coming across this question in the future): It is usually a good idea to test the solutions before accepting them.  In the instant case, the accepted solution will pass both $str1 and $str2.  The correct solution was available here:
https://www.experts-exchange.com/questions/28719388/PHP-Test-if-string-contains-only-numbers-dashes-parentheses-and-spaces.html?anchorAnswerId=40990071#a40990071
Avatar of skij

ASKER

Ray, thanks for your comments.  I solution I accepted provided a working regular expression that met the needs of my original post.  I tested the regular expression and it met my needs, which is why I accepted it as the solution.
Ray, I did check my code before I posted it.  I didn't put it in a loop like you did but it shows the correct results if you manually change the variable in the 'preg_match' line.