2

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

  • 加利福尼亚州洛杉矶
  • 加利福尼亚
  • 90210
  • 橙色 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

4 回答 4

2

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

不过,不确定它的性能如何。

于 2012-06-28T22:01:28.333 回答
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 . "'"
    );
}
于 2012-06-28T22:25:50.990 回答
0

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

如果您使用 Google Maps Geocoder ( https://developers.google.com/maps/documentation/geocoding/#GeocodingRequests ),您基本上可以将任何看起来合理的地址传递给它,它会返回一个结构良好的地址结果。

谷歌的例子: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 (注意 I此处故意拼错以显示 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"
}    
于 2012-06-29T00:04:47.733 回答
0

一个可能的解决方案是只向用户请求一个邮政编码并使用http://www.zippopotam.us/的 api 来获取州和城市,因此不确定这是否符合您的用户体验设计您的要求,但我'已经使用 jquery 使用他们的 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>');
                }
            });
        }
    });
于 2012-06-29T00:24:23.840 回答