从单个字符串猜猜城市,州和邮政编码

时间:2012-06-28 21:52:42

标签: php mysql

所以我有一个位置搜索字段,我想接受几乎所有东西(城市,州和邮政编码),例如:

  • 加利福尼亚州洛杉矶
  • 加利福尼亚
  • 90210
  • Orange CA

那里的任何组合...

从那时起,我将这些单词分成了一个带

的数组
$inputs = preg_split("/[\s,-\/]+/", $input);

这给了我类似的东西

array(5) {
    [0]=> string(4) "Some"
    [1]=> string(4) "City"
    [2]=> string(3) "New"
    [3]=> string(4) "York"
    [4]=> string(5) "88888"
}

然后我先找出邮政编码

foreach ($inputs as $key => $value) {

    if (is_numeric($value) && strlen($value) == 5) {

        $zip = $value;              
        unset($inputs[$key]);
    }
}

注意unset()

现在我需要将状态名称与状态数据库相匹配。困境是一些州的名字中有多个单词(北卡罗来纳州,纽约)。

如何将我的$inputs与州名和缩写相匹配,从我的数组中删除匹配的条件(我必须为下一个城市做同样的事情)?


我正在考虑尝试

$inputString = "'" . implode("','", $inputs) . "'";

$result = mysql_query("SELECT state_name
                      FROM states
                      WHERE state_name IN ({$inputString})
                      OR state_abbrev IN ({$inputString})");

但这并不能说明哪些内容匹配或适用于多字状态

编辑:

对于仇敌,我宁愿没有3个单独的领域。我认为这使用户体验变得复杂。我宁愿让服务器思考而不是他们,以最好地猜测他们尝试传达的位置。我也会有一个“高级”搜索,它将包含这些字段,但所有这些字段都占用了太多空间用于网站设计。

示例:

4 个答案:

答案 0 :(得分:2)

您可以在address表中添加一列,其中包含城市名称,州名称,邮政编码等的串联。然后在其上设置FULLTEXT索引,并在其上运行整个输入字符串的全文搜索。

不确定这表现得如何。

答案 1 :(得分:0)

这就是我目前正在使用的,但有很多循环和查询,我怀疑它是高效的还是“非常准确地猜测”

    function getLocations($input) {

    $state = NULL;
    $zip = NULL;

    $input = strtoupper(trim($input));

    $inputs = preg_split("/[^a-zA-Z0-9]+/", $input);

    // Resolve zip code
    foreach ($inputs as $key => $value) {

        if (is_numeric($value) && strlen($value) == 5) {

            $zip = $value;              
            unset($inputs[$key]);
        }
    }

    $inputs = array_reverse($inputs);

    $result = mysql_query("SELECT state_name, state_abbrev FROM states");

    // Resolve state (one worded)
    while ($row = mysql_fetch_assoc($result)) {

        foreach ($inputs as $key => $value) {

            if ($row['state_abbrev'] == $value || $row['state_name'] == $value) {

                $state = $row['state_abbrev'];
                unset($inputs[$key]);

                return array(
                    'city' => "'" . implode(" ", array_reverse($inputs)) . "'",
                    'state' => "'" . $state . "'",
                    'zip' => "'" . $zip . "'"
                );
            }
        }
    }

    // Resolve state (2/3 worded)
    for ($i = 0; $i < count($inputs) - 1; $i++) {

        $duoValue = @$inputs[$i + 1] . " " . @$inputs[$i];

        if (count($inputs) > $i + 2) {

            $trioValue = $inputs[$i + 2] . " " . $duoValue;
        }

        $result2 = mysql_query("SELECT state_name, state_abbrev FROM states") or die (mysql_error());

        while ($row = mysql_fetch_assoc($result2)) {

            if ($row['state_abbrev'] == $duoValue || $row['state_name'] == $duoValue) {

                $state = $row['state_abbrev'];
                unset($inputs[$i], $inputs[$i + 1]);

                return array(
                    'city' => "'" . implode(" ", array_reverse($inputs)) . "'",
                    'state' => "'" . $state . "'",
                    'zip' => "'" . $zip . "'"
                );
            }
            else if ($i < count($inputs) - 2) {

                if ($row['state_abbrev'] == $trioValue || $row['state_name'] == $trioValue) {

                    $state = $row['state_abbrev'];
                    unset($inputs[$i], $inputs[$i + 1], $inputs[$i + 2]);

                    return array(
                        'city' => "'" . implode(" ", array_reverse($inputs)) . "'",
                        'state' => "'" . $state . "'",
                        'zip' => "'" . $zip . "'"
                    );
                }
            }
        }
    }

    return array(
        'city' => "'" . implode(" ", array_reverse($inputs)) . "'",
        'state' => "'" . $state . "'",
        'zip' => "'" . $zip . "'"
    );
}

答案 2 :(得分:0)

我完全同意您的想法,即让用户轻松使用并在1个单输入框中显示所有地址信息。但是,每个用户可能会以不同的方式输入信息,并且很难找到涵盖每种情况的算法。最好的办法是看看是否有人已经这样做了,正如你所提到的,google有。幸运的是,他们有一个API来解决这个问题。

如果您使用Google地图地理编码器(https://developers.google.com/maps/documentation/geocoding/#GeocodingRequests),您基本上可以将任何合理地看起来像地址的内容传递给它,并且它将返回结构良好的地址结果。

Google的示例:https://google-developers.appspot.com/maps/documentation/javascript/examples/geocoding-simple

另一个例子 - 查找白宫:将此URL放在浏览器中:     http://maps.googleapis.com/maps/api/geocode/json?address=1600%20pennsylvania%20ave%20washongton%20dc&sensor=false(注意我在这里故意拼写错误以显示API的容差)。

API调用返回一个非常有用的JSON对象:

{
   "results" : [
      {
         "address_components" : [
            {
               "long_name" : "1600",
               "short_name" : "1600",
               "types" : [ "street_number" ]
            },
            {
               "long_name" : "Pennsylvania Ave NW",
               "short_name" : "Pennsylvania Ave NW",
               "types" : [ "route" ]
            },
            {
               "long_name" : "Washington",
               "short_name" : "Washington",
               "types" : [ "locality", "political" ]
            },
            {
               "long_name" : "District of Columbia",
               "short_name" : "DC",
               "types" : [ "administrative_area_level_1", "political" ]
            },
            {
               "long_name" : "United States",
               "short_name" : "US",
               "types" : [ "country", "political" ]
            },
            {
               "long_name" : "20502",
               "short_name" : "20502",
               "types" : [ "postal_code" ]
            }
         ],
         "formatted_address" : "1600 Pennsylvania Ave NW, Washington, DC 20502, USA",
         "geometry" : {
            "location" : {
               "lat" : 38.89767770,
               "lng" : -77.03651700000002
            },
            "location_type" : "ROOFTOP",
            "viewport" : {
               "northeast" : {
                  "lat" : 38.89902668029149,
                  "lng" : -77.03516801970852
               },
               "southwest" : {
                  "lat" : 38.89632871970850,
                  "lng" : -77.03786598029153
               }
            }
         },
         "partial_match" : true,
         "types" : [ "street_address" ]
      },
      {
         "address_components" : [
            {
               "long_name" : "1600",
               "short_name" : "1600",
               "types" : [ "street_number" ]
            },
            {
               "long_name" : "Pennsylvania Ave NW",
               "short_name" : "Pennsylvania Ave NW",
               "types" : [ "route" ]
            },
            {
               "long_name" : "Washington",
               "short_name" : "Washington",
               "types" : [ "locality", "political" ]
            },
            {
               "long_name" : "District of Columbia",
               "short_name" : "DC",
               "types" : [ "administrative_area_level_1", "political" ]
            },
            {
               "long_name" : "United States",
               "short_name" : "US",
               "types" : [ "country", "political" ]
            },
            {
               "long_name" : "20500",
               "short_name" : "20500",
               "types" : [ "postal_code" ]
            }
         ],
         "formatted_address" : "1600 Pennsylvania Ave NW, Washington, DC 20500, USA",
         "geometry" : {
            "location" : {
               "lat" : 38.89871490,
               "lng" : -77.03765550
            },
            "location_type" : "ROOFTOP",
            "viewport" : {
               "northeast" : {
                  "lat" : 38.90006388029150,
                  "lng" : -77.03630651970849
               },
               "southwest" : {
                  "lat" : 38.89736591970851,
                  "lng" : -77.03900448029150
               }
            }
         },
         "partial_match" : true,
         "types" : [ "street_address" ]
      },
      {
         "address_components" : [
            {
               "long_name" : "1600",
               "short_name" : "1600",
               "types" : [ "street_number" ]
            },
            {
               "long_name" : "Pennsylvania Ave NW",
               "short_name" : "Pennsylvania Ave NW",
               "types" : [ "route" ]
            },
            {
               "long_name" : "Washington",
               "short_name" : "Washington",
               "types" : [ "locality", "political" ]
            },
            {
               "long_name" : "District of Columbia",
               "short_name" : "DC",
               "types" : [ "administrative_area_level_1", "political" ]
            },
            {
               "long_name" : "United States",
               "short_name" : "US",
               "types" : [ "country", "political" ]
            },
            {
               "long_name" : "20004",
               "short_name" : "20004",
               "types" : [ "postal_code" ]
            }
         ],
         "formatted_address" : "1600 Pennsylvania Ave NW, Washington, DC 20004, USA",
         "geometry" : {
            "location" : {
               "lat" : 38.89549710,
               "lng" : -77.03008090000002
            },
            "location_type" : "ROOFTOP",
            "viewport" : {
               "northeast" : {
                  "lat" : 38.89684608029150,
                  "lng" : -77.02873191970852
               },
               "southwest" : {
                  "lat" : 38.89414811970850,
                  "lng" : -77.03142988029153
               }
            }
         },
         "partial_match" : true,
         "types" : [ "street_address" ]
      },
      {
         "address_components" : [
            {
               "long_name" : "1600",
               "short_name" : "1600",
               "types" : [ "street_number" ]
            },
            {
               "long_name" : "Pennsylvania Ave SE",
               "short_name" : "Pennsylvania Ave SE",
               "types" : [ "route" ]
            },
            {
               "long_name" : "Hill East",
               "short_name" : "Hill East",
               "types" : [ "neighborhood", "political" ]
            },
            {
               "long_name" : "Washington",
               "short_name" : "Washington",
               "types" : [ "locality", "political" ]
            },
            {
               "long_name" : "District of Columbia",
               "short_name" : "DC",
               "types" : [ "administrative_area_level_1", "political" ]
            },
            {
               "long_name" : "United States",
               "short_name" : "US",
               "types" : [ "country", "political" ]
            },
            {
               "long_name" : "20003",
               "short_name" : "20003",
               "types" : [ "postal_code" ]
            }
         ],
         "formatted_address" : "1600 Pennsylvania Ave SE, Washington, DC 20003, USA",
         "geometry" : {
            "bounds" : {
               "northeast" : {
                  "lat" : 38.87865290,
                  "lng" : -76.98170180
               },
               "southwest" : {
                  "lat" : 38.87865220,
                  "lng" : -76.98170229999999
               }
            },
            "location" : {
               "lat" : 38.87865290,
               "lng" : -76.98170180
            },
            "location_type" : "RANGE_INTERPOLATED",
            "viewport" : {
               "northeast" : {
                  "lat" : 38.88000153029150,
                  "lng" : -76.98035306970850
               },
               "southwest" : {
                  "lat" : 38.87730356970850,
                  "lng" : -76.98305103029151
               }
            }
         },
         "partial_match" : true,
         "types" : [ "street_address" ]
      }
   ],
   "status" : "OK"
}    

答案 3 :(得分:0)

一个可能的解决方案就是只需要一个用户的邮政编码,并使用http://www.zippopotam.us/的api来获取州和城市,并且不确定这是否符合你的ux设计你的寻求,但我已经使用jiery使用它们的api完成此操作,该api返回值为

的两个字段
   $("#text-4edcd39ecca23").keyup(function (event) {
        if (this.value.length === 5) {
            var $citywrap = $("#fm-item-text-4edcd393cb50f");
            var $city = $("#text-4edcd38744891");
            var $statewrap = $("#fm-item-text-4edcd38744891");
            var $state = $("#text-4edcd393cb50f");
            var $zip = $('#text-4edcd39ecca23');

            $.ajax({
                url:"http://zippo-zippopotamus.dotcloud.com/us/" + $zip.val(),
                cache:false,
                dataType:"json",
                type:"GET",
                data:"us/" + $zip.val(),
                success:function (result, success) {
                    // Remove Error Message if one is presant
                    $zip.parent().find('small').remove();
                    // US Zip Code Records Officially Map to only 1 Primary Location
                    var places = result['places'][0];
                    $city.val(places['place name']);
                    $state.val(places['state']);
                    $citywrap.slideDown();
                    $statewrap.slideDown();
                },
                error:function (result, success) {
                    $citywrap.slideUp();
                    $statewrap.slideUp();
                    $city.val('');
                    $state.val('');
                    $zip.parent().find('br').remove();
                    $zip.parent().find('small').remove();
                    $zip.after('<br /><small class="error">Sorry your zipcode was not reconized please try again</small>');
                }
            });
        }
    });