Weird whitespace error in PHP - php

I have phone numbers that I want to format
And I have a pattern matcher that breaks down the numbers into a 10 digit format, and then applies dashes.
It works most of the time. However Im having an issue with certain numbers.
$trimmed = trim(preg_replace('/\s+/', '', $v->cust_num));
$tendigit = str_replace(array( '(', ')','-',' ' ), '', $trimmed);
$num = substr($tendigit,0,3)."-".substr($tendigit,3,3)."-".substr($tendigit,6,4);
This will change (555)555 5555, or 555-555 5555 or 5555555555 or (555)-555-5555 or 555-555-5555
to my format of 555-555-5555
However, I came across a few entries in my database, that dont seem to want to change.
One of the bad entries is this one. It contains two white spaces infront of the 4.
4-035-0100
When it runs through $trimmed, and I output $tendigit...it outputs
40350100
as expected. But then when I apply $num to it. It goes back to
4-035-0100
I would at least expect it to be
403-501-00
It seems there is some hidden whitespace in it, that my preg_replace, trim, and str_replace are not attacking.
Any ideas??
Thanks

The code below works, I have tried it with the special characters we discovered in the comments. Basically, the regex removes everything that isnt a number (0-9) and then uses your original formatting.
$trimmed = preg_replace('/\D+/', '', $v->cust_num);
$num = substr($trimmed,0,3)."-".substr($trimmed,3,3)."-".substr($trimmed,6,4);

You can condense your code a little:
$tendigit = preg_replace('/[^\d]/', '', $v->cust_num);
$num = substr($tendigit,0,3)."-".substr($tendigit,3,3)."-".substr($tendigit,6,4);
Though, you should add in some conditions to check that the phone number actually has 10 digits too:
$tendigit = preg_replace('/[^\d]/', '', $v->cust_num);
if(strlen($tendigit == 10)){
$num = substr($tendigit,0,3)."-".substr($tendigit,3,3)."-".substr($tendigit,6,4);
} else {
// catch your error here, eg 'please enter 10 digits'
}
The first line removes any 'non-digit' [^\d].
The conditional statement checks if the $tendigit variable has 10 digits in it.
If it does, then it uses your code to parse and format.
If it doesnt, then you can catch an error.

Related

Preg_matching email and looking for specific text

I have a bunch of emails that I read as text in my program and they all have phone numbers such as these:
+370 655 54298
+37065782505
37069788505
865782825
65782825
(686) 51852
How would I go about finding them and saving it into a variable?
For now I am doing it like this:
$found = preg_match('^[0-9\-\+]{9,15}^', $text, $num);
But it does not working at all
Have a look at the "libphonenumber" Google Library.
There are two functions you may find useful
isPossibleNumber - quickly guessing whether a number is a possible phonenumber by using only the length information, much faster than a full validation.
isValidNumber - full validation of a phone number for a region using length and prefix information.
This should work https://regex101.com/r/E2PzRN/2
#\+?\(?\d+\)?\s?\d+\s?\d+#
<?php
$regex = '#\+?\(?\d+\)?\s?\d+\s?\d+#';
$x = [
'+370 655 54298',
'+37065782505',
'37069788505',
'865782825',
'hjtgfjtdfjtgdfjt',
'65782825',
'(686) 51852',
];
foreach ($x as $y) {
if (preg_match($regex, $y, $match)) {
echo $match[0] . "\n";
}
}
Check it in action here https://3v4l.org/6AlQa
We distinguish here 3 types of phone numbers.
The first type is this one:
+37065782505
37069788505
865782825
65782825
Here, the beginning + is optional. we thus consider that we have 7 digits minimum for these numbers.
The regular expression obtained is therefore
(\+?[0-9]{7,})
The second type is this one:
+370 655 54298
Here we have a first block consisting of a + followed by 2 to 6 digits and then several other blocks of 2 to 6 digits and separated by spaces.
The regular expression obtained is therefore
(\+[0-9]{2,6}(\s[0-9]{2,6})+)
The last type is this one:
(686) 51852
This is a first block consisting of 2 to 6 digits surrounded by parentheses and then several other blocks of 2 to 6 digits and separated by spaces.
The regular expression obtained is therefore
(\([0-9]{2,6}\)(\s[0-9]{2,6})+)
The complete extraction code is therefore
preg_match_all("#(\+?[0-9]{7,})|(\+[0-9]{2,6}(\s[0-9]{2,6})+)|(\([0-9]{2,6}\)(\s[0-9]{2,6})+)#",$text,$out);
$found = $out[0];
where $found is an array.
I would suggest stripping out '+','(',')',' ' and testing if it is a ctype_digit
remove all characters and test if numeric, this assumes that the result is a phone no, if you were to run this on an email address the result would be false
var_dump(ctype_digit(str_replace([' ', '+', '(', ')'], '', '(686) 51852')));
TRUE
var_dump(ctype_digit(str_replace([' ', '+', '(', ')'], '', 'r#pm.mr')));
FALSE

PHP Check if Many spaces before or after a string

On my website, after a user registers they can change their username at any time. The minimum amount of characters is 6 and max amount is 25.
Here's some of the coding to check the length and remove characters:
$users_new_name = strip_tags($_POST['new_name']);
$new_name = preg_replace("/[^0-9a-zA-Z -]/", "", $users_new_name);
// Check Length
if (ctype_space($new_name)) {
$message = die('<span class="Fail">Error: Name Must Be At least 6 Characters Long!</i></span>');
}
if(strlen($new_name) < 6) {
$message = die('<span class="Fail">Error: Name Must Be At least 6 Characters Long!</i></span>');
}
if(strlen($new_name) > 25) {
$message = die('<span class="Fail">Error: Name Can\'t Be More Than 25 Characters Long!</i></span>');
}
The issue I'm having is if you type in 5 spaces and then a letter or number, There new name will be that letter or number; Or if you type in a letter or number then 5 spaces. How could I prevent this from happening?
Here's a screenshot of the example
I do not understand why tags would be in a POST.
Spaces becomes a non-issue if you change:
$users_new_name = strip_tags($_POST['new_name']);
To
$users_new_name = trim(strip_tags($_POST['new_name']));
Or ideally (strip tags is unnecessary):
$users_new_name = trim($_POST['new_name']);
Change the RegEx expression to /[^0-9a-zA-Z]/ to eliminate spaces and dashes.
It sounds like you need trim() to trim any spaces from the username. See http://php.net/trim
ltrim() will trim any leading spaces. rtrim() will trim any spaces at the end of the string.
This is fairly simple and it's something I've had to deal with on systems before.
If you make the first thing you call, this preg_replace, the rest of you code should catch it;
$name = preg_replace('~[\s]+~', '', $name);
This simply checks if there is a space, or more than one, then replaces with a single space.
So " l" would return " l" - failing your 5 character minimum.
Use trim() around this and you should have it working to something acceptable (Depending on your definition of acceptable - worked in my use-case)

Big numbers regex

$value = preg_replace("/[^0-9]+/", '', $value);
How could I edit this regex to get rid of everything after the decimal point? There may or may not be a decimal point.
Currently "100.1" becomes 1001 but it should be 100.
Complete function:
function intfix($value)
{
$value = preg_replace("/[^0-9]+/", '', $value);
$value = trim($value);
return $value + 0;
}
It is used to format user input for numbers as well as servers output to format numbers for the DB. The functions deals with very large numbers, so I can't use intval or similar. Any extra comments to improve this function are welcome.
You could just change the regex to /[^0-9].*/s.
.* matches zero or more characters, so the first character that is not a digit, and the digits that immediately follow, would be deleted.
You need to have a pattern that starts the search with a decimal place. At the moment you're only deleting the . not the numbers after it... So you could do '/\.[\d]+/'
$text = "1201.21 12 .12 12.21";
$text = preg_replace('/\.[\d]+/', '' ,$text);
The above code would result in $text = "1201 12 12"
Why not $value = round($value, 0);? This can handle large values and is meant to get rid of the following decimals mathematically (I'd rather work with numbers as numbers not as strings). You can pass PHP_ROUND_HALF_DOWN as a third parameter if you want to just get rid of the decimals 10.7 -> 10. Or floor($value); could work too.

php preg match a-zA-Z and only one space between 2 or more words

For my PHP script I have this code:
if (!preg_match("/[^A-Za-z]/", $usersurname))
$usersurname_valid = 1;
This worked untill I realized a surname can be two or more words... doh.
Anyone can tell me how to write this code if I want to allow 1 space between two worlds? For example:
Jan Klaas is now wrong and Jan Klaas should be allowed, also Jan Klaas Martijn and so on should be allowed.
Even better would be a preg replace, to replace two or more spaces with 1, so when you write: Jan(space)(space)Klaas or Jan(space)(space)(space)(space)Klaas, it would return Jan(space)Klaas.
I searched around for a while but somehow I just can't get this space matching to work..
PS: When I got this working, I will apply this for the mid and last name too ofcourse.
===========================================
EDIT: After you helping me out, I re-wrote my code to:
// validate usersurname
$usersurname = preg_replace("/\s{2,}/"," ", $usersurname);
if (!preg_match("/^[A-Za-z]+(\s[A-Za-z]+)*$/",$usersurname))
$usersurname_valid = 1;
// validate usermidname
$usermidname = preg_replace("/\s{2,}/"," ", $usermidname);
if (!preg_match("/^[A-Za-z]+(\s[A-Za-z]+)*$/",$usermidname))
$usermidname_valid = 1;
// validate userforename
$userforename = preg_replace("/\s{2,}/"," ", $userforename);
if (!preg_match("/^[A-Za-z]+(\s[A-Za-z]+)*$/",$userforename))
$userforename_valid = 1;
and the error notifications
elseif ($usersurname_valid !=1)
echo ("<p id='notification'>Only alphabetic character are allowed for the last name. $usersurname $usermidname $userforename</p>");
// usermidname character validation
elseif ($usermidname_valid !=1)
echo ("<p id='notification'>Only alphabetic character are allowed for the middle name. $usersurname $usermidname $userforename</p>");
// userforename character validation
elseif ($userforename_valid !=1)
echo ("<p id='notification'>Only alphabetic character are allowed for the (EDIT) first name. $usersurname $usermidname $userforename</p>");
Replacing the spaces are working well and I need this preg_match to check on on A-Za-z + space. I think in this case it doesn't matter if it's matching more than 1 spaces because it's replaced anyway, right?
EDIT:
Solution for my case:
$usersurname = preg_replace("/\s{2,}/"," ", $usersurname);
if (!preg_match("/[^A-Za-z ]/", $usersurname))
This does the work. Thanks for helping out, J0HN
Well, solving the problem you have in mind:
if (!preg_match("/^[A-Za-z]+(\s[A-Za-z]+)*$/",$usersurname)) { ... }
But, well, it's just a part of the solution, and it's not bulletproof. Look at the list of common mistakes when handling names.
So, you'd better to re-think on your validation approach.
Replacing the multiple spaces is simpler to achieve as a separate instruction, something like
$processed_usersurname = preg_replace("/\s{2,}/"," ", $usersurname);
This will match and replace any two or more consequent whitespace characters (space, tab, linebreak and carriage return) to single space

Extract numbers from phone number input field (PHP)

I've got a phone number input field, which allows a user to add a phone number in whatever format they want (555-555-5555, (555) 555 - 5555, etc).
Since it a phone number field only, I can ignore everything but the numbers in the field.
I'm currently using the following code. It extracts all the numbers, but the issue is that they are not in order - it's in a jumbled order.
How do I extract the numbers in the order that they appear in the original string?
preg_match_all('/\d+/', $Phone, $matches);
$Phone = implode('', $matches[0]);
Edit: They are actually not in a jumbled order from this function - I was inserting the numbers into a int(10) database field, which caused the jumbling. But, the answers below are still a more efficient way of accomplishing my goal.
Use preg_replace to remove any non-digits:
$numbers = preg_replace('/[^\d]/','',$Phone);
Note: '[^\d]' can be replaced with '\D' (safe in non-unicode mode).
$Phone = preg_replace('/[^\d]/', '', $Phone);
Why not just replace everything in the string that is not a digit?
$number = preg_replace("/[^0-9]/", '', $Phone);
Try it
if (!preg_match("/^[0-9\-]*$/",$Phone)) {
echo "Only Numeric and strip (-)";
}
Example:
Good: 0877-9320-9356
Failed: 0877 9320 9356 or 087793209356

Categories