【问题标题】:Creating a Store Locator with PHP, MySQL & Google Maps a little different使用 PHP、MySQL 和 Google 地图创建商店定位器有点不同
【发布时间】:2011-12-07 09:12:08
【问题描述】:

我想使用 Google 地图创建商店定位器。

我有一个数据库,其中包含一个旅游对象表(带有它们的坐标)和一个酒店表(也带有它们的坐标)。

我希望用户能够在加载伦敦塔的页面后,比如说,查看 10 公里半径内的对象附近有哪些酒店,并在带有标记的 Google 地图上显示结果。

到目前为止,我只成功地使用haversin公式从数据库中获取了10公里范围内的酒店并将它们显示为文本:

$result = mysql_query("SELECT  nume,  poze, descriere, link, (
(
    ACOS( SIN( 45.515038 * PI( ) /180 ) * SIN( latitudine * PI( ) /180 ) +
          COS( 45.515038 * PI( ) /180 ) * COS( latitudine * PI( ) /180 ) *
          COS( ( 25.366935 - longitudine ) * PI( ) /180 )
    ) *180 / PI( )
) *60 * 1.1515 * 1.609344
) AS distance
FROM `unitati`
HAVING distance <= '10'
ORDER BY distance ASC
LIMIT 0 , 30");

如何将它们显示为地图上的标记?

我找到了这个,我认为它可以帮助我:http://code.google.com/intl/ro-RO/apis/maps/articles/phpsqlsearch.html,但它有一个不同的逻辑:用户输入地址。

【问题讨论】:

    标签: php mysql google-maps


    【解决方案1】:

    此示例获取您的查询(您需要使用每个目标的 lat/lng 编辑 45.515038 和 25.366935)并将其输出为 JS 数组数组(如果您愿意,可以使其更正式的 JSON)

    然后循环遍历该数组,为每个数组制作标记并将它们放置在地图上。最后,它为每个添加一个点击监听器,以便显示相关信息。

    <!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Transitional//EN" "http://www.w3.org/TR/xhtml1/DTD/xhtml1-transitional.dtd">
    <html xmlns="http://www.w3.org/1999/xhtml">
    <head>
    <meta http-equiv="Content-Type" content="text/html; charset=utf-8" />
    <title>Untitled Document</title>
    <script type="text/javascript" src="http://maps.googleapis.com/maps/api/js?sensor=false"></script>
    <style>
    #map_canvas{width:500px;height:500px;}
    </style>
    </head>
    
    <body>
    <div id="map_canvas"></div>
    <script>
    <?php
    //you'll first need to connect to your db
    //you also have to edit the lat/lng in your SELECT statement to be that of your objective
    $result = mysql_query("SELECT  latitudine, longitudine, nume,  poze, descriere, link, (
    (
        ACOS( SIN( 45.515038 * PI( ) /180 ) * SIN( latitudine * PI( ) /180 ) +
              COS( 45.515038 * PI( ) /180 ) * COS( latitudine * PI( ) /180 ) *
              COS( ( 25.366935 - longitudine ) * PI( ) /180 )
        ) *180 / PI( )
    ) *60 * 1.1515 * 1.609344
    ) AS distance
    FROM `unitati`
    HAVING distance <= '10'
    ORDER BY distance ASC
    LIMIT 0 , 30");
    $c=0;
    echo "var data=[";
    while($markers=mysql_fetch_array($result)){
        if($c>0){echo ",";}
        echo "['".$markers[0]."','".$markers[1]."','".$markers[2]."','".$markers[3]."','".$markers[4]."','".$markers[5]."','".$markers[6]."'"."]";
        $c++;
    }
    echo "];";
    ?>
        //var data=[['45','-73','home','poz1','desc1','link1'],['43','-75','work','poz2','desc2','link2']];
        var places=new Array();
        var map;
        var MyInfoWindow = new google.maps.InfoWindow({content: 'Loading...'});
        var bounds = new google.maps.LatLngBounds();
        var myOptions = {
            zoom: 9,
            mapTypeControl: false,
            mapTypeId: google.maps.MapTypeId.ROADMAP
        };
        map = new google.maps.Map(document.getElementById('map_canvas'),myOptions);
        for(i=0;i<data.length;i++){
            var point=new google.maps.LatLng(data[i][0],data[i][1]);
            var a = new google.maps.Marker({position: point,map: map, icon:'someHotelIcon.png'});
            a.lat=data[i][0];
            a.lng=data[i][1];
            a.nume=data[i][2];
            a.poze=data[i][3];
            a.desc=data[i][4];
            a.url=data[i][5];
            places.push(a);
        }
        for(i=0;i<places.length;i++){
            var point2=new google.maps.LatLng(places[i].lat,places[i].lng);
            bounds.extend(point2);
        }
        map.fitBounds(bounds);
        var objLoc=new google.maps.LatLng(45.515038,26.366935);
        var objectiveMarker = new google.maps.Marker({position: objLoc,map: map, icon:'objectiveIcon.png'});    //---------------Marker for objective
        for (var i = 0; i < places.length; i++) {
            var marker = places[i];
            google.maps.event.addListener(marker, 'click', function () {
            MyInfoWindow.setContent(this.nume+'<br/>'+this.desc+'<br/><a href=\"'+this.url+'\">link</a>');
            MyInfoWindow.open(map, this);
            });
        }
    </script>
    </body>
    </html>
    

    【讨论】:

    • 每个目标都有自己的 php 页面,但我没有你说的“功能搜索位置附近”。我只有一个查询,我在问题中写的那个告诉数据库只检索位于 10 公里范围内的酒店。请更具体
    • 只需将每页查询中的 lat/LNG(45.5 和 25.3)替换为目标坐标
    • 这是一个让您入门的示例页面
    • 你的例子太酷了!谢谢 !我能够在地图上显示酒店,但是,因为总是有一个但是,如果我取消注释该 var 行,它只显示该点,它不显示搜索结果。奇怪..
    • 这是因为该行覆盖了搜索结果,它需要是/或,很高兴它有帮助
    【解决方案2】:

    如果您要进行基于距离/地理位置的搜索,请使用 MySQL 的地理空间资料。它比直接的半正弦公式更有效。

    这些只是一些 sn-ps,但它们应该可以帮助您走上令人敬畏的道路:

    首先,您的桌子需要一个地理空间列来保存您的纬度/经度,我的称为坐标,类型为 point

    `coordinate` point NOT NULL,
    

    接下来您需要添加地理空间索引:

    SPATIAL KEY `coordinate` (`coordinate`)
    

    (这两个都是我的 table create sql 语法的一部分)。

    此位将有助于将您的纬度/经度数据插入坐标列:

    $data['coordinate'] = ("GeomFromText( 'POINT({$data['longitude']} {$data['latitude']})')");
    

    这一点将取代您的距离计算(作为更大 SQL 查询的一部分):

    $sql = str_replace(
                array('%LATITUDE%','%LONGITUDE%'), 
                array($latitude, $longitude),
                '(GLength( LineString( coordinate ,Point(%LONGITUDE%, %LATITUDE%)))) AS distance'
            );
    

    上述查询适用于欧几里得几何(即世界是平的),但世界并非如此,因此您应该使用以下查询来帮助缩小结果列表。为了获得真正的准确性和正确的排序,请对从这 2 个 SQL 查询返回的结果使用半正弦或更好的公式。

    这个位将作为一个边界矩形/框(任何不在框内的东西都不会被返回——用它来替换HAVING distance &lt;= '10',你会发现查询更快——尤其是有大量数据时)。我对最大/最小纬度/经度的计算只是示例,您可以做得更好:-) :

            $minLat = $latitude - 0.5;
            $maxLat = $latitude + 0.5;
            $minLon = $longitude - 0.5;
            $maxLon = $longitude + 0.5;
    
            $sql = str_replace(
                array('%MINLAT%', '%MAXLAT%','%MINLON%', '%MAXLON%'), 
                array($minLat, $maxLat, $minLon, $maxLon),
                "MBRCONTAINS(GeomFromText('POLYGON((%MINLON% %MAXLAT%,%MAXLON% %MAXLAT%,%MAXLON% %MINLAT%,%MINLON% %MINLAT%, %MINLON% %MAXLAT%))'), `coordinate`)"
            );
    

    【讨论】:

    • 我发现 hasrsin 公式是一种更简单的方法,考虑到我对这一切都是新手。从逻辑上讲,我一开始不会有很多酒店,所以目前我想我会继续使用哈弗辛公式。我对谷歌地图上酒店的视觉显示很感兴趣,我该怎么做。我怀疑它可以用商店定位器完成,但我需要一些提示
    • 很多取决于硬件,但我发现普通的haversine对于几千行是可以的,但超过这个性能确实会下降。如果您认为您将获得接近 50,000+ 的任何地方,那么一定要看看 GeoSpatial。 (别担心,你可以稍后实现它而不会太痛苦)我从来没有真正尝试过在谷歌地图上显示东西,所以我必须让其他人帮助你
    • 我希望我的数据库中有 50 000 家酒店 :) 一开始我会很高兴有几百家酒店 :)
    • 然后你避免使用地理空间查询,除非你有时间来实现它们。一旦你发现你的查询太慢了,你就可以重构你的代码
    • (如果您发现这个问题很有用,那么点个赞就好了 :-)
    猜你喜欢
    • 1970-01-01
    • 2015-03-28
    • 1970-01-01
    • 1970-01-01
    • 2011-04-24
    • 1970-01-01
    • 1970-01-01
    • 2013-08-08
    • 1970-01-01
    相关资源
    最近更新 更多