PHP字符串求值方法

发布于 2024-10-30 20:24:32 字数 545 浏览 2 评论 0原文

希望一位伟大的思想家能在这里帮助我。

我遇到过这样的情况:我将从提供商处收到国际电话号码,我必须进行数据库查找并找出该电话号码所呼叫的国家、地区和电话类型。

例如,假设我将收到电话号码+393234567891。我必须在表格中查找电话号码所属的国家/地区。所以我知道“39”是意大利,我将其作为数据库中的国家/地区代码,但我必须确定该号码是固定电话还是手机。为此,我需要电话号码中的更多信息,因此“39”是固定电话,“393”是手机。我需要看到电话号码包含“393”,因此我知道它是一部手机。

我的问题是评估这一点的最佳方法是什么?是否会循环遍历电话号码的每个部分,例如首先将前两个电话号码与数据库进行比较,然后是前三个,然后是前四个,直到我返回一个结果?例如,如果我继续这个示例并将意大利的“39”与数据库进行比较,我将返回一堆结果,因为有“39”、“393”和“3939”等等。那么使用整个电话号码来获得电话号码前缀的精确匹配的最佳方法是什么?

我本想只循环遍历电话号码并将电话号码的一位数字添加到循环中,直到我返回只有一个结果,我只是想确保这是完成此操作的最有效方法。

有什么建议吗?谢谢!

Hoping one of the great minds can help me here.

I have a situation where I will receive an international phone number from a provider and I have to do a database lookup and figure out the country, region, and phone type that the phone number is calling.

For example, say I will receive a phone number +393234567891. I have to look up in a table the country that phone number belongs to. so I know that '39' is Italy, and I have that as a country code in the database but I have to determine whether the number is a landline or a cell phone. For that I need more information out of the phone number so '39' is a landline and '393' is a cell phone. I need to see that the phone number contains '393' and therefore I know that it is a cell phone.

My question is what is the best way to evaluate this? Would it be to loop through each segment of the phone number like first compare the first two phone numbers against the database, then the first three, then the first four until I come back with one single result? For example, if I continue with this example and compare '39' for Italy against the db I will come back with a bunch of results because there are '39' and '393' and '3939' and so on. So what is the best way to use the entire phone number to get the exact match for the phone number prefix?

I would have thought to just loop through the phone number and add a digit of the phone number to the loop until I come back with only one result, I just want to make sure that this is the most efficient way to accomplish this.

Any recommendations? Thanks!

如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。

扫码二维码加入Web技术交流群

发布评论

需要 登录 才能够评论, 你可以免费 注册 一个本站的账号。

评论(4

悲歌长辞 2024-11-06 20:24:32

我假设你有一个像这样的表:

prefix (id, number)

数据如下:

1, '39'
2, '393'
3, '33'
4, '331'

你可以得到最长反向LIKE的匹配:

SELECT id
FROM prefix
WHERE "393234567891" LIKE CONCAT(number, "%")
ORDER BY LENGTH(number)
LIMIT 1;

我还没有测试过它,但假设你的最短前缀是2字符,您可能会得到一些改进(这只会检查以 39 开头的前缀,即您拥有的所有前缀的 1%):

SELECT id
FROM prefix
WHERE "393234567891" LIKE CONCAT(number, "%")
    AND number LIKE "39%"
ORDER BY LENGTH(number)
LIMIT 1;

然后您可以有一个不同的表,其中附加了信息前缀如:

prefixinfo (id, prefix_id, type, data)

数据如:

1, 1, 'country', 'Italy'
2, 2, 'country', 'Italy'
3, 2, 'type',    'Landline'
4, 3, 'country', 'France'
5, 4, 'country', 'France'
6, 4, 'city',    'Paris'

I assume you have a table like:

prefix (id, number)

with data like:

1, '39'
2, '393'
3, '33'
4, '331'

You can get the longest match with a reverse LIKE:

SELECT id
FROM prefix
WHERE "393234567891" LIKE CONCAT(number, "%")
ORDER BY LENGTH(number)
LIMIT 1;

I have not tested it, but assuming your shortest prefix is 2 characters, you may get some improvement with (this will only check prefixes starting with 39, that is 1% of all the prefixes you have):

SELECT id
FROM prefix
WHERE "393234567891" LIKE CONCAT(number, "%")
    AND number LIKE "39%"
ORDER BY LENGTH(number)
LIMIT 1;

Then you can have a different table with the informaton attached to that prefix like:

prefixinfo (id, prefix_id, type, data)

with data like:

1, 1, 'country', 'Italy'
2, 2, 'country', 'Italy'
3, 2, 'type',    'Landline'
4, 3, 'country', 'France'
5, 4, 'country', 'France'
6, 4, 'city',    'Paris'
楠木可依 2024-11-06 20:24:32

如果实际电话号码是固定大小的,您可以将其删除。与 sub_strreplace ;例如,数字长度为 8 位:

$code = substr_replace($number,'',-1,8);

$code 现在将仅包含代码部分。这样您就可以轻松数出数字并找出您需要的内容。

if an actual phone number is fixed size you can remove it. with sub_strreplace; e.g. numbers are 8 digits long:

$code = substr_replace($number,'',-1,8);

$code now will contain only code part. so you can easily count digits and find out what you need.

花期渐远 2024-11-06 20:24:32

393中最后的3表示手机,每个国家都一样吗?

理想的情况是有一个国家/地区表,然后有另一个包含相关前缀的表

Countries table                        Subsearch Table

countryMatch: 39                       substrMatch: 3 // for 393              
countryName: "Italy"                   substrCountry: 39
                                       substrMeaning: "cell"
                                       ...................
                                       substrMatch: 5 // 395
                                       substrCountry: 39
                                       substrMeaning: "something else"

这样,一旦您确定了国家/地区,您就可以限制其余搜索以进一步限制例如 393、3939。

我认为您提出的方法是合理的,一点一点地循环,直到使用 SQL 查询找到匹配项。因此,通过弹出前两位数字 (39) 来查找国家/地区代码,如果找到,则查询子搜索表以获取结果。有了这些结果,循环将它们附加到国家/地区代码中,看看是否获得匹配,

$subsearchArr = array("3" => "cell","5" => "something else") # from the database 
$match = false;
$country = 39;

foreach($subsearchArr as $key => $value)
{
  # append $key to $country e.g. 393, 395
  # if this is a match to the string
  # set match to true and do your logic
}

if($match == false) # no match so landline
{
  # logic here if landline
}

我认为这可行,但我想我必须查看确切的数据结构才能确定。但是,两张桌子绝对是可取的

The last 3 that signifies a mobile in 393, is that the same for every country?

The ideal situation would be to have a table for countries and then another table with related prefixes

Countries table                        Subsearch Table

countryMatch: 39                       substrMatch: 3 // for 393              
countryName: "Italy"                   substrCountry: 39
                                       substrMeaning: "cell"
                                       ...................
                                       substrMatch: 5 // 395
                                       substrCountry: 39
                                       substrMeaning: "something else"

That way once you have determined the country you can limit the rest of your searches for further limiting e.g. 393, 3939.

I reckon your proposed method is sound, looping through bit by bit till you find a match using SQL queries. So find the country code by popping off the first two digits (39), and if found query the subsearch table for results. With those results loop through appending them to the country code and see if you get a match

$subsearchArr = array("3" => "cell","5" => "something else") # from the database 
$match = false;
$country = 39;

foreach($subsearchArr as $key => $value)
{
  # append $key to $country e.g. 393, 395
  # if this is a match to the string
  # set match to true and do your logic
}

if($match == false) # no match so landline
{
  # logic here if landline
}

I reckon that would work, but I guess i'd have to see the exact data structure to be sure. But yeah two tables is definitely desirable

花想c 2024-11-06 20:24:32

即使您在 Mysql 中拥有数据,在 PHP 中使用简单的数组循环进行比较可能会更好。从数据库(和缓存)构建一个包含预期国家/地区代码和每个国家/地区内已知唯一前缀的 PHP 数组,以区分手机、固定电话、区域等。

对于您拥有的每个国家/地区代码,查看输入的电话号码是否以该代码开头。找到国家/地区后,从电话号码中删除国家/地区代码,然后根据该国家/地区的已知手机号码前缀列表测试剩余的号码。如果找到,则它是移动的。如果找不到,则为固定电话。

例如,在希腊,国家/地区代码为 30,所有手机均以 69 开头。但是,如果您所在的国家/地区的手机号码前缀与区号无法区分(例如美国和加拿大),那么您就不走运了。

function checkMSISDN($msisdn) {

    $countries = array(
        'gr' => array(
            'countryPrefix' => '30',
            'mobilePrefix' => '3069',
            'length' => 12,
        ),
        'it' => array(
            'countryPrefix' => '39',
            'mobilePrefix' => '393',
            'length' => 12,
        ),
    ) ;

    foreach ($countries as $countryName => $countryRules)  {

        $msisdnCurrent = $msisdn ;

        $countryPrefix = $countryRules['countryPrefix'] ;
        $fullPrefix = $countryRules['mobilePrefix'] ;

        //remove leading + if any
        if (substr($msisdnCurrent, 0, 1) == '+') {
            $msisdnCurrent = substr($msisdnCurrent, 1) ;
        }

        //remove leading 00 if any
        if (substr($msisdnCurrent, 0, 2) == '00') {
            $msisdnCurrent = substr($msisdnCurrent, 2) ;
        }

        $msisdnLength = strlen($msisdnCurrent) ;
        if ($msisdnLength != $countryRules['length']) {
            //sanity check, not this country
            continue ;
        }

        if (substr($msisdnCurrent, 0, strlen($countryPrefix)) != $countryPrefix) {
            //not this country
            continue ;
        }

        if (substr($msisdnCurrent, 0, strlen($fullPrefix)) != $fullPrefix) {
            //not mobile
            return "isLandline" ;
        }
        else {
            //mobile
            return "isMobile" ;
        }
    }
    return false ;
}

It may be better to do the comparisons in PHP with simple array loops, even if you have the data in Mysql. Build from the database (and cache) a PHP array of expected country codes and known unique prefixes within each country to differentiate between mobile, landline, areas etc.

For each country code you have, see if the input phone number starts with that code. Once you find the country, remove the country code from the phone number and test the remaining number against a list of known mobile number prefixes in that country. If found, it's mobile. If not found, it's landline.

For instance, in Greece the country code is 30 and all mobiles start with 69 after that. If, however, you're realing with countries where mobile number prefixes are indistinguishable from area codes (such as USA and Canada) you are out of luck.

function checkMSISDN($msisdn) {

    $countries = array(
        'gr' => array(
            'countryPrefix' => '30',
            'mobilePrefix' => '3069',
            'length' => 12,
        ),
        'it' => array(
            'countryPrefix' => '39',
            'mobilePrefix' => '393',
            'length' => 12,
        ),
    ) ;

    foreach ($countries as $countryName => $countryRules)  {

        $msisdnCurrent = $msisdn ;

        $countryPrefix = $countryRules['countryPrefix'] ;
        $fullPrefix = $countryRules['mobilePrefix'] ;

        //remove leading + if any
        if (substr($msisdnCurrent, 0, 1) == '+') {
            $msisdnCurrent = substr($msisdnCurrent, 1) ;
        }

        //remove leading 00 if any
        if (substr($msisdnCurrent, 0, 2) == '00') {
            $msisdnCurrent = substr($msisdnCurrent, 2) ;
        }

        $msisdnLength = strlen($msisdnCurrent) ;
        if ($msisdnLength != $countryRules['length']) {
            //sanity check, not this country
            continue ;
        }

        if (substr($msisdnCurrent, 0, strlen($countryPrefix)) != $countryPrefix) {
            //not this country
            continue ;
        }

        if (substr($msisdnCurrent, 0, strlen($fullPrefix)) != $fullPrefix) {
            //not mobile
            return "isLandline" ;
        }
        else {
            //mobile
            return "isMobile" ;
        }
    }
    return false ;
}
~没有更多了~
我们使用 Cookies 和其他技术来定制您的体验包括您的登录状态等。通过阅读我们的 隐私政策 了解更多相关信息。 单击 接受 或继续使用网站,即表示您同意使用 Cookies 和您的相关数据。
原文