Ok, so I've already got the bulk of this worked out... I've got a function right now that will run a pattern check on the phone number it's given and then determine whether it's a "valid" phone number based on the NANPA guidelines.
However, the problem I'm running into is that it allows people to enter "extension" numbers, but I can't figure out how to allow them in multiple formats.
For example:
It would take the following phone number: (123) 456-7890 x345 and mark it as valid... However, if I were to try using: (123) 456-7890 ext345 then it marks it as invalid.
The regex pattern I'm using for the initial check is one I found on the web, and I've done barely any modifications to it thusfar... I've made it so that it allows "." as a separator between numbers, but that's it.
Here's the function: (long winded, I know)
/*
* Function to validate a US phone number and split it into it's 3 components
* 3-digit area code, 3-digit exchange code, 4-digit subscriber number
*/
function validPhone($phone) {
  //Set the regex pattern
  $pattern = '/^[\(]?(\d{0,3})[\)]?[\.]?[\/]?[\s]?[\-]?(\d{3})[\s]?[\.]?[\/]?[\-]?(\d{4})[\s]?[x]?(\d*)$/';
  //Set variable to false
  $valid = array(
    'ac'=>false,
    'ec'=>false,
    'sn'=>false,
    'en'=>false,
    'all'=>false,
  );
  //Look for match, then dump patterns to $matches
  if (preg_match($pattern, $phone, $matches)) {
    // Original number
    $phone_number = $matches[0];
    // 3-digit area code
    $area_code = $matches[1];
    // Validate area code based on NANPA standards
    if(ereg('^[2-9]{1}[0-8]{1}[0-9]{1}$', $area_code)) {
      if($area_code != '555') {
        $valid['ac'] = true;
      }
    }
    // 3-digit exchange code
    $exchange_code = $matches[2];
    // Validate exchange code based on NANPA standards
    if(ereg('^[2-9]{1}[0-9]{2}$', $exchange_code)) {
      $valid['ec'] = true;
    }
    // 4-digit subscriber number
    $sub_number = $matches[3];
    // Double check that subscriber number is 0-9 only
    if(ereg('^[0-9]{4}$', $sub_number)) {
      $valid['sn'] = true;
    }
    // Extension number (if entered)
    $ext_number = $matches[4];
    // Double check that extension is 0-9 only
    if(!empty($ext_number)) {
      if(ereg('^[0-9]*$', $ext_number)) {
        $valid['en'] = true;
      }
    }
    echo '<h1>Parsing phone number: '.$phone_number.'</h1>';
    echo '<h4>Area Code: '.$area_code.'</h4>';
    echo '<h4>Exchange Code: '.$exchange_code.'</h4>';
    echo '<h4>Subscriber Number: '.$sub_number.'</h4>';
    if(!empty($ext_number)) {
      echo '<h4>Extension: '.$ext_number.'</h4>';
    }
    else {
      echo '<h4>No Extension Found</h4>';
    }
    echo '<hr />';
    // Check that all are valid 
    // before setting final variable
    if($valid['ac']) {
      echo '<h5>Step 1: Area code is valid</h5>';
      if($valid['ec']) {
        echo '<h5>Step 2: Extension code is valid</h5>';
        if($valid['sn']) {
          echo '<h5>Step 3: Subscriber number is valid</h5>';
          if(!empty($ext_number) && $valid['en']) {
            echo '<h5>Step 4: Extension number is valid</h5>';
            $valid['all'] = true;
          }
          elseif(empty($ext_number)) {
            echo '<h5>Step 4: Extension number not set, continuing</h5>';
            $valid['all'] = true;
          }
        }
      }
    }
  }
  return $valid['all'];
}
I know it's not setup for efficiency right now, I have echoes everywhere for debugging...
Here's a few examples of formats it will and won't validate:
123-456-7890x123 = validates
123.456.7890x123 = validates
123 456 7890 x123 = validates
(123) 456-7890 x123 = validates  
123-456-7890ex123 = doesn't validate
123.456.7890 ex123 = doesn't validate
123 456 7890 ext123 = doesn't validate  
Basically, the only way it validates when extensions are entered is if the extension is in the format: x123 (with or without a leading space)
Any other format such as ex, ext, ext:, ex: etc... None of them work.
I know it has to be the original regex pattern, but I can't figure out how to solve it.
Any ideas?
EDIT: I've mixed and modified two of the answers given below to form the full function which now does what I had wanted and then some... So I figured I'd post it here in case anyone else comes looking for this same thing.
/*
 * Function to analyze string against many popular formatting styles of phone numbers
 * Also breaks phone number into it's respective components
 * 3-digit area code, 3-digit exchange code, 4-digit subscriber number
 * After which it validates the 10 digit US number against NANPA guidelines
*/
function validPhone($phone) {
  $format_pattern = '/^(?:(?:\((?=\d{3}\)))?(\d{3})(?:(?<=\(\d{3})\))?[\s.\/-]?)?(\d{3})[\s\.\/-]?(\d{4})\s?(?:(?:(?:(?:e|x|ex|ext)\.?\:?|extension\:?)\s?)(?=\d+)(\d+))?$/';
  $nanpa_pattern = '/^(?:1)?(?(?!(37|96))[2-9][0-8][0-9](?<!(11)))?[2-9][0-9]{2}(?<!(11))[0-9]{4}(?<!(555(01([0-9][0-9])|1212)))$/';
  //Set array of variables to false initially
  $valid = array(
    'format' => false,
    'nanpa' => false,
    'ext' => false,
    'all' => false
  );
  //Check data against the format analyzer
  if(preg_match($format_pattern, $phone, $matchset)) {
    $valid['format'] = true;    
  }
  //If formatted properly, continue
  if($valid['format']) {
    //Set array of new components
    $components = array(
      'ac' => $matchset[1], //area code
      'xc' => $matchset[2], //exchange code
      'sn' => $matchset[3], //subscriber number
      'xn' => $matchset[4], //extension number
    );
    //Set array of number variants
    $numbers = array(
      'original' => $matchset[0],
      'stripped' => substr(preg_replace('[\D]', '', $matchset[0]), 0, 10)
    );
    //Now let's check the first ten digits against NANPA standards
    if(preg_match($nanpa_pattern, $numbers['stripped'])) {
      $valid['nanpa'] = true;
    }
    //If the NANPA guidelines have been met, continue
    if($valid['nanpa']) {
      if(!empty($components['xn'])) {
        if(preg_match('/^[\d]{1,6}$/', $components['xn'])) {
          $valid['ext'] = true;
        }
      }
      else {
        $valid['ext'] = true;
      }
    }
    //If the extension number is valid or non-existent, continue
    if($valid['ext']) {
      $valid['all'] = true;
    }
  }
  return $valid['all'];
}