views:

351

answers:

5

Hi all,

I have a form that collects information, one piece of which is a phone number. The phone number data comes from three fields, one for an area code, for the first 3 digits, and for the last four, so that numbers are in this format: xxx-xxx-xxxx (basic U.S. format).

These three fields are not required, but I would like to do some basic error checking if someone decides to fill out any combination of the three field:

(let's say they only give me the area code - that means that they wanted to give me their number, so in essence, it becomes required, so the code should check to see that 1) all three data sets were sent, and 2) all three are only numbers)

Here is what I thought would work, but it does not:

if((isset($_POST['numArea'], $_POST['numFirst'], $_POST['numSecond']) && (!ctype_digit(trim($_POST['numArea'])) || !ctype_digit(trim($_POST['numFirst'])) || !ctype_digit(trim($_POST['numSecond'])) || strlen(trim($_POST['numArea'])) !== 3 || strlen(trim($_POST['numFirst'])) !== 3 || strlen(trim($_POST['numSecond'])) !== 4))
  || (isset($_POST['numArea']) XOR isset($_POST['numFirst']) XOR isset($_POST['numArea']))){
    $errors[] = 'Please give us a valid Phone Number, or remove any numbers if you do not wish to use your phone number.';
  }else{
   $_POST['PhoneNumber'] = '+01'.$_POST['numArea'].'-'.$_POST['numFirst'].'-'.$_POST['numSecond']; }

Any suggestions?

A: 

Just check if one of the fields is not set;

if (!isset($_REQUEST['numFirst']) || !isset($_REQUEST['numSecond']) || !isset($_REQUEST['numArea'])) {
    if (!isset($_REQUEST['numFirst'])) {
         print 'Please fill out the FIrst area';
    }
    if (!isset($_REQUEST['numSecond'])) {
         print 'Please fill out the Second area';
    }
    if (!isset($_REQUEST['numArea'])) {
         print 'Please fill out the Area code';
    }
}

Is that the kind of thing you wanted to do?

Christian
Although, I am not too happy with that as there are too many calls to isset... I will rewrite it to be cleaner if this is the thing you are after.
Christian
I think he wants to check if any of the fields is set too. If none of them are filled in it's ok too.
koen
+1  A: 

First of all if those fields are inputs then isset() will always return true. What you probably want to check is if they are not empty. So you should use empty() function for that.

I will replace your form values with $a, $b and $c to make it simple.

$a = $_POST['numArea'];
$b = $_POST['numFirst'];
$c = $_POST['numSecond'];

if (!empty($a) || !empty($b) || !empty($b)) {
    // we know now that at least field was filled in, lets check their values
    $regex = '/^\d+$/';
    if (!preg_match($regex, $a) || !preg_match($regex, $b) || !preg_match($regex, $c)) {
        echo "Phone number invalid";
    }
}

This is just an example. You could shorten it to just one if statement but I haven't done so to make it more readable.

RaYell
Would a space return !empty() as true? If so, I would need to trim() the POST variable, assign it to a second var, and then test that var with !empty().This is close to what I need, I just need to write two different regexes - one to accept only 3 digits, and one to only accept 4.
Andrew E.
Things considered to be empty:http://us3.php.net/manual/en/function.empty.phpA space (or a number of them) are not on the list.
Andrew E.
Don't worry about spaces. Regex will catch them.
RaYell
Or you could just `trim()` the `$a`, `$b` and `$c` values in the example. If you want the regex to match exactly 4 digits use this `'/^\d{4}$/'`.
RaYell
+4  A: 

The reason why your code isn't working is not because of your boolean logic, but because of your use of isset(). In the case of a <input type="text">, the $_POST['fieldName'] will always be set, regardless of if the value is empty or not.

Use $_POST['fieldName'] != '' instead to determine if the user has entered a value. DO NOT USE empty(), as this will return any falsy value as empty (0, 000, false, etc...).


Personally, I rather use one <input type="type"> for the phone number. This is less annoying than making the user switch boxes, and also makes validation simpler.

This example actually validates if the number follows NANP rules. I find it absolutely ridiculous that so many applications/websites oversees this validation step.

// Did the user post a number?
if($_POST['phone'] != '') {

  // Get only the numbers, we don't care how the user formatted their number
  $_POST['phone'] = preg_replace('/[^0-9]/', '', $_POST['phone']);

  // Is it a valid NANP phone number?
  if(preg_match('/^1?[2-9][0-8][0-9][2-9][0-9]{6}$/i', $_POST['phone']) === 1) {
    echo "Valid NANP phone number";

    // Trim the leading one
    $_POST['phone'] = ltrim($_POST['phone'], '1');

    // Format as wanted
    $_POST['PhoneNumber'] = '+01'.substr($_POST['phone'],0,3).'-'.substr($_POST['phone'],3,3).'-'.substr($_POST['phone'],6,4);
  } else {
    echo "Invalid phone number";
  }
} else {
  echo "User didn't provide phone number";
}
Andrew Moore
This is great, except that I don't accept the data as one string, but three. I'm using parts of your regex with RaYell's !empty() approach right now, will post finalized version and give the answer to the one I feel helped the most.
Andrew E.
**@Andrew E.:** Using 3 different inputs not only complicates your code, but also complicates the entry process for the user. I strongly recommend using one input.
Andrew Moore
And like I said in my post, **do not use `empty()`**.
Andrew Moore
You've convinced me! I'm changing the way my app works. Thanks for the great line of code. The formating was only for presentation, The major thing is that I get the number in e164 format, which is trivial from here.Thanks!
Andrew E.
A: 

Hi, This is not solution for your problem , but it will solve it other-way , try imask

it's actually a JS script .

openidsujoy
Yeah, I plan to use something like imask - this is just a backup security measure, in case js fails, or the user has it disabled.
Andrew E.
Note that doing "validation" on the client-side does abolutly not prevent from doing validation on the server-side : "validation" in JS is just to be more user-friendly, and eventually avoiding a client-server trip ; but it does definitly not garantee data will effectivly valid : JS can be disabled, form POSTing can be faked -- so, even if it helps, it won't solve anything ;-)
Pascal MARTIN
A: 

Well first off, if anyone is ever gonna be able to maintain your code, you'll have to break that up into method calls. I'd probably write it something like this:

public function phoneNumberWasProvided () {
   return !(empty($_POST['numArea']) && 
            empty($_POST['numFirst']) && 
            empty($_POST['numSecond']));

}

public function phoneNumberIsValid () {
   $this->_phoneErrors = array();
   // The following three if statements can also be
   // extracted into their own methods
   if(!preg_match("/^\d{3}/$", $_POST['numArea']) {
      $this->_phoneErrors['numArea'] = 'The area code you provided is invalid';
   }
   if(!preg_match("/^\d{3}/$", $_POST['numFirst']) {
      $this->_phoneErrors['numFirst'] = 'The first part of the provided phone 
                                         number is invalid';
   }
   if(!preg_match("/^\d{4}/$",$_POST['numSecond']) {
      $this->_phoneErrors['numArea'] = 'The first part of the provided phone 
                                        number is invalid';
   }

   return empty($this->_phoneErrors);
}

Now you can easily use these methods inside your main logic, making it more readable:

if($this->phoneNumberWasProvided()) {
    if(!$this->phoneNumberIsValid()) {
        $errors = $this->getPhoneNumberErrors();
        // Print errors / do whatever is necessary
    } else {
       $phoneNumber = 
         "{$_POST['numArea']}-{$_POST['numFirst']}-{$_POST['numSecond']}";
    }
}
PatrikAkerstrand