Метод оценки строк PHP


Надеюсь, что один из великих умов сможет помочь мне здесь.

У меня есть ситуация, когда я получаю международный номер телефона от провайдера, и мне нужно сделать поиск в базе данных и выяснить страну, регион и тип телефона, по которому звонит телефонный номер.

Например, скажите, что я получу номер телефона +393234567891. Я должен посмотреть в таблице страну, которой принадлежит этот номер телефона. так что я знаю, что '39' - Это Италия, и у меня есть это как код страны в но я должен определить, является ли номер стационарным или сотовым телефоном. Для этого мне нужно больше информации из номера телефона, поэтому "39" - это стационарный телефон, а " 393 " - мобильный телефон. Мне нужно видеть, что номер телефона содержит "393", и поэтому я знаю, что это сотовый телефон.

Мой вопрос в том, как лучше всего это оценить? Будет ли это петля через каждый сегмент телефонного номера, как сначала сравнить первые два телефонных номера с базой данных, а затем первый три, потом первые четыре, пока я не вернусь с единственным результатом? Например, если я продолжу этот пример и сравню "39" для Италии с db, я вернусь с кучей результатов, потому что есть " 39 " и " 393 " и "3939" и так далее. Итак, как лучше всего использовать весь телефонный номер, чтобы получить точное соответствие для префикса телефонного номера?

Я бы подумал, что нужно просто перебрать телефонный номер и добавить цифру телефонного номера в петлю, пока я не вернусь. имея только один результат, я просто хочу убедиться, что это самый эффективный способ достичь этого.

Какие-нибудь рекомендации? Спасибо!

4 2

4 ответа:

Я предполагаю, что у вас есть таблица, подобная:

prefix (id, number)

С такими данными, как:

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

Вы можете получить Самое длинное совпадение с обратным, как :

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'

Если фактический номер телефона имеет фиксированный размер, вы можете удалить его. с sub_strreplace; например, числа имеют длину 8 цифр:

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

$code теперь будет содержать только часть кода. таким образом, вы можете легко посчитать цифры и узнать, что вам нужно.

Последние 3, которые означают мобильный телефон в 393, это то же самое для каждой страны?

Идеальной ситуацией было бы иметь таблицу для стран, а затем другую таблицу со связанными префиксами

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
}

Я думаю, что это сработает, но я думаю, что мне нужно увидеть точную структуру данных, чтобы быть уверенным. Но да, две таблицы определенно желательно

Возможно, лучше делать сравнения в PHP с простыми циклами массива, даже если у вас есть данные в Mysql. Постройте из базы данных (и кэша) массив 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 ;
}