Google Map API 结合PHP实现登录地图定位

来源:互联网 发布:类似美团能省钱软件 编辑:程序博客网 时间:2024/04/27 19:41

Google Map API 结合PHP实现登录定位主要思想是在用户登录系统时记录下IP地址,在通过相关的地址索引由IP转换到物理地址,最后通过Google Map API将取得的物理地址标示在Google地图上。

 

php平台由ThinkPHP框架搭建。具体流程图如下:


 

这里用到了CoralWry这个数据文件,网上有的下载的,以前的彩虹QQ什么的都是用这个文件解析的,不过可能有时候需要更新IP的缘故会对此文件进行更新,下面有下载包。这个文件放在根目录下

 

继续,在TP中引入一下两个文件作为外链调用库,可以直接放入TP核心文件夹的Lib下的ORG扩展库中

IpLocation类,这个扩展类是从DAT文件中将IP提取地址所用

 

Php代码  收藏代码
  1. class IpLocation {  
  2. var $fp;  
  3. var $firstip;  //第一条ip索引的偏移地址  
  4. var $lastip;   //最后一条ip索引的偏移地址  
  5. var $totalip;  //总ip数  
  6. //*  
  7. //构造函数,初始化一些变量  
  8. //$datfile 的值为纯真IP数据库的名子,可自行修改.  
  9. //*  
  10. function ipLocation($datfile = "CoralWry.Dat"){  
  11.   $this->fp=fopen($datfile,'rb')or die("CoralWry.Dat不存在,请去网上下载纯真IP数据库, 'CoralWry.dat' 放到当前目录下");   //二制方式打开  
  12.   $this->firstip = $this->get4b(); //第一条ip索引的绝对偏移地址  
  13.   $this->lastip = $this->get4b();  //最后一条ip索引的绝对偏移地址  
  14.   $this->totalip =($this->lastip - $this->firstip)/7 ; //ip总数 索引区是定长的7个字节,在此要除以7,  
  15.   register_shutdown_function(array($this,"closefp"));  //为了兼容php5以下版本,本类没有用析构函数,自动关闭ip库.  
  16. }  
  17. //*  
  18. //关闭ip库  
  19. //*  
  20. function closefp(){  
  21. fclose($this->fp);  
  22. }  
  23. //*  
  24. //读取4个字节并将解压成long的长模式  
  25. //*  
  26. function get4b(){  
  27.   $str=unpack("V",fread($this->fp,4));  
  28.   return $str[1];  
  29. }  
  30. //*  
  31. //读取重定向了的偏移地址  
  32. //*  
  33. function getoffset(){  
  34.   $str=unpack("V",fread($this->fp,3).chr(0));  
  35.   return $str[1];  
  36. }  
  37. //*  
  38. //读取ip的详细地址信息  
  39. //*  
  40. function getstr(){  
  41.     $str="";  
  42.   $split=fread($this->fp,1);  
  43.   while (ord($split)!=0) {  
  44.     $str .=$split;  
  45.     $split=fread($this->fp,1);  
  46.   }  
  47.   return $str;  
  48. }  
  49. //*  
  50. //将ip通过ip2long转成ipv4的互联网地址,再将他压缩成big-endian字节序  
  51. //用来和索引区内的ip地址做比较  
  52. //*  
  53. function iptoint($ip){  
  54.   return pack("N",intval(ip2long($ip)));  
  55. }  
  56. //*  
  57. //获取客户端ip地址  
  58. //注意:如果你想要把ip记录到服务器上,请在写库时先检查一下ip的数据是否安全.  
  59. //*  
  60. function getIP() {  
  61.         if (getenv('HTTP_CLIENT_IP')) {  
  62.                 $ip = getenv('HTTP_CLIENT_IP');   
  63.         }  
  64.         elseif (getenv('HTTP_X_FORWARDED_FOR')) { //获取客户端用代理服务器访问时的真实ip 地址  
  65.                 $ip = getenv('HTTP_X_FORWARDED_FOR');  
  66.         }  
  67.         elseif (getenv('HTTP_X_FORWARDED')) {   
  68.                 $ip = getenv('HTTP_X_FORWARDED');  
  69.         }  
  70.         elseif (getenv('HTTP_FORWARDED_FOR')) {  
  71.                 $ip = getenv('HTTP_FORWARDED_FOR');   
  72.         }  
  73.         elseif (getenv('HTTP_FORWARDED')) {  
  74.                 $ip = getenv('HTTP_FORWARDED');  
  75.         }  
  76.         else {   
  77.                 $ip = $_SERVER['REMOTE_ADDR'];  
  78.         }  
  79.         return $ip;  
  80. }  
  81. //*  
  82. //获取地址信息  
  83. //*  
  84. function readaddress(){  
  85.   $now_offset=ftell($this->fp); //得到当前的指针位址  
  86.   $flag=$this->getflag();  
  87.   switch (ord($flag)){  
  88.          case 0:  
  89.              $address="";  
  90.          break;  
  91.          case 1:  
  92.          case 2:  
  93.              fseek($this->fp,$this->getoffset());  
  94.              $address=$this->getstr();  
  95.          break;  
  96.          default:  
  97.              fseek($this->fp,$now_offset);  
  98.              $address=$this->getstr();  
  99.          break;  
  100.   }  
  101.   return $address;  
  102. }  
  103. //*  
  104. //获取标志1或2  
  105. //用来确定地址是否重定向了.  
  106. //*  
  107. function getflag(){  
  108.   return fread($this->fp,1);  
  109. }  
  110. //*  
  111. //用二分查找法在索引区内搜索ip  
  112. //*  
  113. function searchip($ip){  
  114.   $ip=gethostbyname($ip);     //将域名转成ip  
  115.   $ip_offset["ip"]=$ip;  
  116.   $ip=$this->iptoint($ip);    //将ip转换成长整型  
  117.   $firstip=0;                 //搜索的上边界  
  118.   $lastip=$this->totalip;     //搜索的下边界  
  119.   $ipoffset=$this->lastip;    //初始化为最后一条ip地址的偏移地址  
  120.   while ($firstip <= $lastip){  
  121.     $i=floor(($firstip + $lastip) / 2);          //计算近似中间记录 floor函数记算给定浮点数小的最大整数,说白了就是四舍五也舍  
  122.     fseek($this->fp,$this->firstip + $i * 7);    //定位指针到中间记录  
  123.     $startip=strrev(fread($this->fp,4));         //读取当前索引区内的开始ip地址,并将其little-endian的字节序转换成big-endian的字节序  
  124.     if ($ip < $startip) {  
  125.        $lastip=$i - 1;  
  126.     }  
  127.     else {  
  128.        fseek($this->fp,$this->getoffset());  
  129.        $endip=strrev(fread($this->fp,4));  
  130.        if ($ip > $endip){  
  131.           $firstip=$i + 1;  
  132.        }  
  133.        else {  
  134.           $ip_offset["offset"]=$this->firstip + $i * 7;  
  135.           break;  
  136.        }  
  137.     }  
  138.   }  
  139.   return $ip_offset;  
  140. }  
  141. //*  
  142. //获取ip地址详细信息  
  143. //*  
  144. function getaddress($ip){  
  145.   $ip_offset=$this->searchip($ip);  //获取ip 在索引区内的绝对编移地址  
  146.   $ipoffset=$ip_offset["offset"];  
  147.   $address["ip"]=$ip_offset["ip"];  
  148.   fseek($this->fp,$ipoffset);      //定位到索引区  
  149.   $address["startip"]=long2ip($this->get4b()); //索引区内的开始ip 地址  
  150.   $address_offset=$this->getoffset();            //获取索引区内ip在ip记录区内的偏移地址  
  151.   fseek($this->fp,$address_offset);            //定位到记录区内  
  152.   $address["endip"]=long2ip($this->get4b());   //记录区内的结束ip 地址  
  153.   $flag=$this->getflag();                      //读取标志字节  
  154.   switch (ord($flag)) {  
  155.          case 1:  //地区1地区2都重定向  
  156.          $address_offset=$this->getoffset();   //读取重定向地址  
  157.          fseek($this->fp,$address_offset);     //定位指针到重定向的地址  
  158.          $flag=$this->getflag();               //读取标志字节  
  159.          switch (ord($flag)) {  
  160.                 case 2:  //地区1又一次重定向,  
  161.                 fseek($this->fp,$this->getoffset());  
  162.                 $address["area1"]=$this->getstr();  
  163.                 fseek($this->fp,$address_offset+4);      //跳4个字节  
  164.                 $address["area2"]=$this->readaddress();  //地区2有可能重定向,有可能没有  
  165.                 break;  
  166.                 default//地区1,地区2都没有重定向  
  167.                 fseek($this->fp,$address_offset);        //定位指针到重定向的地址  
  168.                 $address["area1"]=$this->getstr();  
  169.                 $address["area2"]=$this->readaddress();  
  170.                 break;  
  171.          }  
  172.          break;  
  173.          case 2: //地区1重定向 地区2没有重定向  
  174.          $address1_offset=$this->getoffset();   //读取重定向地址  
  175.          fseek($this->fp,$address1_offset);    
  176.          $address["area1"]=$this->getstr();  
  177.          fseek($this->fp,$address_offset+8);  
  178.          $address["area2"]=$this->readaddress();  
  179.          break;  
  180.          default//地区1地区2都没有重定向  
  181.          fseek($this->fp,$address_offset+4);  
  182.          $address["area1"]=$this->getstr();  
  183.          $address["area2"]=$this->readaddress();  
  184.          break;  
  185.   }  
  186.   //*过滤一些无用数据  
  187.   if (strpos($address["area1"],"CZ88.NET")!=false){  
  188.       $address["area1"]="未知";  
  189.   }  
  190.   if (strpos($address["area2"],"CZ88.NET")!=false){  
  191.       $address["area2"]=" ";  
  192.   }  
  193.   return $address;  
  194.  }  
  195.   
  196. }   

 

 

mapService类,方法类

 

 

Php代码  收藏代码
  1. /** 
  2.  * Google Map Service 
  3.  * 2011.4.8 
  4.  */  
  5. import("ORG.IPA.IpLocation");  
  6. class mapService{  
  7.       
  8.     public static function getIPaddress($ip){  
  9.           
  10.     //返回格式  
  11.     $format = "text";//默认text,json,xml,js  
  12.     //返回编码  
  13.     $charset = "utf8"//默认utf-8,gbk或gb2312  
  14.     $ip_l=new IpLocation();  
  15.     $address=$ip_l->getaddress($ip);  
  16.     $address["area1"] = iconv('GB2312','utf-8',$address["area1"]);  
  17.     $address["area2"] = iconv('GB2312','utf-8',$address["area2"]);  
  18.     $add=$address["area1"].$address["area2"];  
  19.     if($add=="本机地址 "){  
  20.         $add="杭州";  
  21.     }  
  22.       
  23.     return  $add;  
  24.     }  
  25. }  
 

然后就可以在登陆的Action接口函数中调用两个文件类了:

 

 

Php代码  收藏代码
  1. import("ORG.IPA.MapService");  
  2.        $ipaddress = get_client_ip();  
  3.   
  4. $adrInfo=MapService::getIPaddress($ipaddress);  
 

 

接下去就可以将上述信息记录到数据库中了,而在用户进入地图页面便可以将数据从数据库导出,并发送到view层进行显示,并在前端层调用Google Map API

 

后台控制层代码很简单:

 

 

Php代码  收藏代码
  1. public function map(){  
  2.       
  3.     parent::islogin();  
  4.     $model = D("Topicview");  
  5.       
  6.        $list =  $model->field('id,tid,imgid,avatar,address,create_time,topic_from,content,nickname,rootid,homepage')  
  7.         ->where("Topic.status=1 and Topic.type='first'")  
  8.         ->order("id desc")  
  9.         ->find();  
  10.   
  11.     //dump($list);  
  12.     $this->assign('addrList',$list);  
  13.     parent::showSiteInfo("Lab前端实验室 - Map Position");  
  14.        $this->display();  
  15.          
  16. }  
 

 

接下来是前台模板层js代码:

 

 

Js代码  收藏代码
  1. if (typeof flowg == "undefined" || !flowg) {  
  2.     var flowg = {};  
  3. }  
  4. flowg.initMap = (function(){  
  5.   
  6.     var htmlString = '<div style="overflow: auto;">' +  
  7.     '<div style="width:300px;overflow:hidden;" class="map-item">' +  
  8.     '<div class="map-left">' +  
  9.     '<img src="{:getUserAvatar($addrList["avatar"],50)}" alt="{$addrList.nickname}" style="border:1px solid #ccc;padding:1px;">' +  
  10.     '</div><div class="map-right">' +  
  11.     '<div class="map-content">{$addrList.nickname} : {$addrList.content}</div>' +  
  12.     '<div class="time">他在{$addrList.address}</div>' +  
  13.     '</div>' +  
  14.     '</div>';  
  15.     var geocoder;  
  16.     var map;  
  17.     var oldinfo = null;  
  18.     function initialize(){  
  19.         geocoder = new google.maps.Geocoder();  
  20.         var latlng = new google.maps.LatLng(34.016, 103.535);  
  21.         var myOptions = {  
  22.             zoom: 8,  
  23.             center: latlng,  
  24.             mapTypeId: google.maps.MapTypeId.ROADMAP  
  25.         };  
  26.         map = new google.maps.Map(document.getElementById("map_canvas"), myOptions);  
  27.         codeAddress("{$addrList.address}", htmlString);  
  28.     }  
  29.       
  30.     function codeAddress(address, html){  
  31.         geocoder.geocode({  
  32.             'address': address  
  33.         }, function(results, status){  
  34.             if (status == google.maps.GeocoderStatus.OK) {  
  35.                 map.setCenter(results[0].geometry.location);  
  36.                 var marker = new google.maps.Marker({  
  37.                     map: map,  
  38.                     position: results[0].geometry.location  
  39.                 });  
  40.                 var contentString = html;  
  41.                 var infowindow = new google.maps.InfoWindow({  
  42.                     content: contentString  
  43.                 });  
  44.                 infowindow.open(map, marker);  
  45.                 if (oldinfo != null) {  
  46.                     oldinfo.close();  
  47.                 }  
  48.                 oldinfo = infowindow;  
  49.             }  
  50.             else {  
  51.                 return false;  
  52.             }  
  53.         });  
  54.     }  
  55.   
  56.     return initialize;  
  57.       
  58. })();  
  59.   
  60. $(flowg.initMap);  
 

 

上面直接调用了google map的marker功能对于信息进行展示,效果图:

 


原创粉丝点击