how to compare 2 phone numbers PHP - php

I have several ways to write a phone number :
+5511999999999
55999999999
11999999999
999999999
is there any library or logic way to compare phone numbers in PHP?

Interesting question.
In order to compare two strings (as phone number or email for example) you have to be sure to have them written in similar format.
I suggest to perform validation of the entry of your forms when you get the phone numbers from the user. This way will allow you to compare strings that have the same template. for example: Country code: [+XXX] Area Code: [(XXX)] Phone Number: [XXX-XXXX]
The user should write something like +44(887)345-5532 (for UK PHONE).
If you have file or list with some phones that you would like to compare, you have to come up with a criteria for Country code, area code and actual phone number in order to compare them with no mistakes.
When this is done you can split the string and compare each element.
There are many open source methods of doing such validation. Try and use ZEND FRAMEWORK, or CAKE PHP, CODE IGNITER or some similar framework and see how to do it there.
Hope that helps.

An interesting approach to the problem could be considering a percentage of similarity. For this case you could use similar_text. I built a function thtat takes an array of phone numbers and compares them to one number like this:
function similarPhone($search, $phones, $acceptablePercentage)
{
foreach ($phones as $phone) {
similar_text($search, $phone, $percentage);
if ($percentage >= $acceptablePercentage) {
return true;
}
}
return false;
}
So I use an acceptable percentage of 80% to compare.

Related

Does a string contain any of a list of substrings in PHP?

I am adding a feature to an application that allows authorised oil rig personnel to submit weather reports (for use by our pilots when planning flights) to our system via email. The tricky part is that we want to match these reports to a particular oil platform, but the personnel (and their email accounts) can move between rigs.
We already have a list of waypoints that each have an "aliases" field. Basically if the email subject contains something in the aliases field, we should match the email to that waypoint.
The subject could be "Weather report 10 April # 1100 Rig A for you as requested"
The aliases for that waypoint would be something like
"RRA RPA Rig A RigA"
Keep in mind there is a similar list of aliases for all the other waypoints we have.
Is there a better way of matching than iterating through each word of each alias and checking if it's a substring of the email subject? Because that sounds like a n^2 sort of problem.
The alternative is for us to put a restriction and tell the operators they have to put the rig name at the start or end of the subject.
This sounds more like an algorithms question than a PHP question specifically. Take a look at What is the fastest substring search algorithm?
Well you can transform this into something like an O(n log n) algorithm, but it depends on the implementation specifics of stripos():
define('RIG_ID_1', 123);
define('RIG_ID_2', 456);
function get_rig_id($email_subject) {
$alias_map = [
'RRA' => RIG_ID_1,
'RPA' => RIG_ID_1,
'Rig A' => RIG_ID_1,
'RigA' => RIG_ID_1,
// ...
];
foreach(array_keys($alias_map) as $rig_substr) {
if(stripos($email_subject, $rig_substr) !== false) {
return $alias_map[$rig_substr];
}
}
return null;
}
Here each substring is examined by stripos() exactly once. Probably a better solution is to compose these strings into a series of regexes. Internally, the regex engine is able to scan text very efficiently, typically scanning each character only one time:
ex.:
<?php
define('RIG_ID_1', 123);
define('RIG_ID_2', 456);
function get_rig_id($email_subject) {
$alias_map = [
'/RRA|RPA|Rig\\sA|RigA/i' => RIG_ID_1,
'/RRB|RPB|Rig\\sB|RigB/i' => RIG_ID_2,
// ...
];
foreach(array_keys($alias_map) as $rig_regex) {
if(preg_match($rig_regex, $email_subject)) {
return $alias_map[$rig_regex];
}
}
return null;
}
For your purposes the practical solution is very much dependent upon how many rigs you've got an how many substrings per rig. I suspect that unless you're dealing with tens of thousands of rigs or unless performance is a critical aspect of this application, a naive O(n^2) solution would probably suffice. (Remember that premature optimization is the root of all evil!) A simple benchmark would bear this out.
An even-better solution -- and potentially faster -- would be to set up an elasticsearch instance, but once again that may be too much effort to go to when a naive approach would suffice in a fraction of the implementation time.

MySql datatype versus PHP formatting whilst not losing numeric sorting capabilities

See http://pdga-europe.com/standings-2015/
It's probably the simplest question you've seen in a while, but I'm stumped.
I am importing an XLS sheet to MySql database, and most data is integers, but some (really, only some) are fractions (at an exact .5)
Data type gets set to DECIMAL (4,1) by PHPMyAdmin, and all math is correct (I'm sorting all data DESC (for the ones with "0" as totaled, I'm using a non-visible column "totaled" to sort by).
What I want to see is the following:
All integers in that particular column (ET3) to display as integers (and not as xxx.0), and ONLY the others as yyy.5?
VARCHAR would at least DISPLAY it right, but it would obviously prevent me from sorting the data in any way other than alphabetical (where 9 all of a sudden comes before 88).
What road should I take to get this right?
Should I find the correct data type, or should I do the formatting in PHP?
Currently my data gets generated this way:
<..query bla bla ..>
printf("
<tr>
<td>%s</td>
</tr>\n",
$row["ET3"]);
}
Thank you.
You should not modify the data type storing these values, because you really dealing with a matter only of display logic. Internally, as long as some of them have a decimal part, all should be stored with a decimal part as a numeric type, rather than as a VARCHAR type.
So you should handle the display logic in PHP, and it can be done many different ways. Retrieving values from MySQL, you will have a string rather than a PHP float value in $row['ET3'], making it easy to handle with basic string operations like substr(). You may test if the last two characters of are ".0" and truncate it with intval(). For example:
// Intval truncates the .0
echo intval('9.0');
// 9
Using a ternary to perform the switch in one line:
echo substr($row["ET3"], -2) == ".0" ? intval($row["ET3"]) : $row["ET3"];
That expression stuffed into your existing printf() works as:
printf("
<tr>
<td>%s</td>
</tr>\n",
(substr($row["ET3"], -2) == ".0" ? intval($row["ET3"]) : $row["ET3"]));
Which can be expressed in expanded form as something like this, though the ternary above is more compact in your existing printf() context.
if (substr($row["ET3"], -2) == ".0") {
// Truncate to an integer
// intval($row["ET3"])
}
else {
// Return the full original value (N.5)
// $row["ET3"];
}
Finally, if you want to use this in more than one place, consider wrapping it in a function:
function truncInt($value) {
return substr($value, -2) == ".0" ? intval($value) : $value;
}
Then just use truncInt($row["ET3"]) in your original printf()...

Restrict Phone numbers with pattern like 0123456789, 8888888888, 9999999999, etc

I need to restrict phone numbers with patterns like:
0123456789,
1111111111,
2222222222,
3333333333,
4444444444,
etc.
I am trying to do it in PHP.
So far i came up with creating an array and searching in it to restrict that mobile no.
Is there any better way to do the same?
Maybe a regex or maybe in javascript.
If you don't want to keep updating a long array of numbers to check against like you mention yourself you basically want to do pattern detection / pattern recognition.
This can be everything from trivial to very complicated depending on your previous knowledge.
A small start can be found here... But there are tons of very thick books on the subject ;)
http://en.wikipedia.org/wiki/Pattern_recognition
So the "easiest" way is probably to use an array look up. The downside is that you must know every single number you wish to blacklist beforehand. A middle way would be to have an array of regexps of invalid formats that you check against instead of having the actual numbers in the array.
So you could have regexps covering things like
Numbers to short
Numbers to long
Numbers with only the same digits
etc
Depending on available systems and geographical location it might actually be possible to do some kind of look up against some known database of numbers. But that could lead to false positives for unlisted numbers.
For a global, dynamic, working system keeping a look up array and doing look ups against databases could both prove to become very hard to handle since the number of known data sources to keep working support for might grow to large to handle.
If you need to block specific phone numbers, you could do this:
$numberToTest = [...]; // this is your user input number to test
$notAllowed = array(
'0123456789',
'1111111111',
'2222222222',
// and so on
);
if(in_array($numberToTest, $notAllowed)) {
// NOT VALID
}
else {
// VALID
}
to match all numbers like 1111111111, 2222222222, etc you could do this:
if(preg_match('/^(\d)\1{9}$/', $numberToTest)) {
// NOT VALID
}
else {
// VALID
}
Javascript with regexp. isRestricted is set to true when the number is in restricted list:
var number = "0123456789";
var isRestricted = number.match( /0123456789|1111111111|2222222222|3333333333|4444444444/g ) != null;
I'm sure regexps works with PHP pretty much the same way using preg_match.

Recipe Calculator

I am creating a website that stores recipes. I am wanting to make a recipe scaler-where you can enter the desired servings, and the script will convert the recipe ingredients to match it. I can change the amount easy enough, but I'm trying to figure out how to convert units. Now I know I can go and put in 1500 if/then statements, but I'm trying to make it a bit simpler. :)
I was looking at a site called Tasty Kitchen. They POST the servings via AJAX to this file (http://tastykitchen.com/recipes/wp-admin/admin-ajax.php), and that file returns the ingredients. Then they display them on the page. Go to http://tastykitchen.com/recipes/breads/plain-bagels/ for an example.
I would REALLY appreciate any help I can get.
Thanks!
My suggestion would be to store a single serve in your database, then simply multiply out how many people you want to feed on the page.
So, if your user has selected they want to make the meal for 4 people, you keep a variable (session, cookie, whatever) - lets call it $peeps for this example - when you output the data you do soemthing like this:
Echo "This will make $peeps portions:";
Echo "Ingredients:<br>";
Echo ($peeps*Ingredient1Quantity)." - ".$ingredient1Name."<br>";
Echo ($peeps*Ingredient2Quantity)." - ".$ingredient2Name."<br>";
and so on.
If you want your site to also convert from imperial to metric, you can do it easily enough with a simple function.
If you store all your data in metric in the database (or Imperial, but all the same type) you can output it easily enough by converting it in a similar manner to the user based on their preference:
// Assumes a function that converts to Imperial from Metric called convertToImperial()
Echo "This will make $peeps portions:";v
Echo "Ingredients:<br>";
Echo convertToImperial($peeps*Ingredient1Quantity)." - ".$ingredient1Name."<br>";
Echo convertToImperial($peeps*Ingredient2Quantity)." - ".$ingredient2Name."<br>";
Edit: If you store everything in the database in Metric, you can then have a function return the data to you in the best Imperial measurement.
// For example, input is passed as
// $qty=30 (ml)
// $serves is passed as 3 (ie, three people)
// $type is passed as liquid.
function convertToImperial($qty, $serves, $type)
{
// Metric to Imperial will need a $type passed (Liquid, Weight, Other).
// You can use a switch statement to pass between the different types.
switch ($type)
{
case "Liquid":
// Assumes 5ml is a teaspoon
// Assumes 15ml is a tablespoon
// Assumes 250ml is a cup.
$CalMeasure=$qty*$serves; // Now at 90ml.
// Here you can now choose to either pick the best match
// ie, measurement with least remainder/exact measure
// which in this case would be 6 tablespoons
// or
// switch measurement types after a certain quantity is reached.
if ($CalMeasure>125) // Half a cup
{
return (round($CalMeasure/250,2)." cups");
}
elseif ($CalMeasure>15) // tablespoons
{
return (round($CalMeasure/15,2)." Tablespoons");
}
else
{
return (round($CalMeasure/5,2)." Teaspoons");
}
break;
case "Weight":
// Similar approach to Weights, Convert Grams to Pounds and the like.
return $WeightMeasured;
break;
default: // assumes Other (pinches, sprinkles etc
// Similar approach again.
break;
}
#Caleb - Fluffeh is right on here with his strategy in regards to storing everything in one type of measurement and then having a series of functions to convert them to others. I built a web application https://Gredio.com that does recipe scaling among other things and was able to produce very flexible reports in this way. One additional difficulty is around liquid measures versus weight. Large scale food production is always done by weight, but the small guys sometimes misunderstand the difference. Doing liquid to weight conversions programmatically can be complex as you need to know the liquids weight which will vary greatly (think honey versus water...)

Divide amount by characters present in string, found via regex

Suggestions for an updated title are welcome, as I'm having trouble easily quantifying what I'm trying to do.
This is a web-based form with PHP doing the calculations, though this question probably has an algorithmic or language agnostic answer.
Essentially, there is an Amount field and a Charge Code field.
The Charge code entered represents a short-hand for several 'agents' to whom the Amount is divided by. Most cases are single letters, however there are a couple cases where this varies, and gives a bit of trouble.
Basically, A = AgentType1, J = AgentType2, L = AgentType3, and as paperwork and user requirements would have it, "A2" is also a valid replacement for "J".
So an amount of 50 and a Charge Code of "AJ" would result in the Amount being divided by 2 (two agents) and dispersed accordingly. The same for a string like "AA2".
I have currently set up process (that works) that goes like this:
Divide = 0;
RegEx check for AgentType1 in Charge Code:
Divide++;
Set This-AgentType-Gets-Return;
RegEx check for AgentType2 in Charge Code:
Devide++;
Set This-AgentType-Gets-Return;
... etc ...
Then I divide the Amount by the "Divide" amount, and the result gets divvied up to each AgentType present in the Charge Code.
I know there must be an easier/simpler way to implement this, but it's not coming to me at the moment.
Is there a way to quickly derive the number of AgentTypes involved in the Charge Code, and which they are?
I would probably just do something simple like this:
$valid_codes = array('A', 'J', 'L');
// deal with the special A2 case first, to get it out of the string
// this code could be generalized if more special cases need to be handled
if (stripos($charge_code, 'A2') !== FALSE)
{
$found['J'] = true;
str_ireplace('A2', '', $charge_code);
}
foreach ($valid_codes as $code)
{
if (stripos($charge_code, $code) !== FALSE) // if the code was in the string
{
$found[$code] = true;
}
}
Now you can get the number you need to divide amount by with count($found), and the codes you need to divide between with array_keys($found).
Can you change the charge code field to an array of fields? Something like:
<input type="hidden" name="agent[]" value="A" />
for all your agents would let you do:
$divide = count($_POST["agent"]);
foreach($_POST["agent"] as $agent) {
$sum = $_POST["amount"] / $divide;
//do other stuff
}
Couldn't you match the string by something like this regex
^([A-Z]\d*)*$
and then work through the generated match list? The divisor would just be the length of this list (perhaps after removing duplicates).
For mapping symbols to Agents (why AgentTypes?), you could use a simple associative list, or a hashmap (I don't know what kind of constructs are easiest available in PHP).

Categories