Google Map API 结合PHP实现登录地图定位
Google Map API 结合PHP实现登录定位主要思想是在用户登录系统时记录下IP地址,在通过相关的地址索引由IP转换到物理地址,最后通过Google Map API将取得的物理地址标示在Google地图上。
?
php平台由ThinkPHP框架搭建。具体流程图如下:
?
这里用到了CoralWry这个数据文件,网上有的下载的,以前的彩虹QQ什么的都是用这个文件解析的,不过可能有时候需要更新IP的缘故会对此文件进行更新,下面有下载包。这个文件放在根目录下
?
继续,在TP中引入一下两个文件作为外链调用库,可以直接放入TP核心文件夹的Lib下的ORG扩展库中
IpLocation类,这个扩展类是从DAT文件中将IP提取地址所用
?
class IpLocation {var $fp;var $firstip; //第一条ip索引的偏移地址var $lastip; //最后一条ip索引的偏移地址var $totalip; //总ip数//*//构造函数,初始化一些变量//$datfile 的值为纯真IP数据库的名子,可自行修改.//*function ipLocation($datfile = "CoralWry.Dat"){ $this->fp=fopen($datfile,'rb')or die("CoralWry.Dat不存在,请去网上下载纯真IP数据库, 'CoralWry.dat' 放到当前目录下"); //二制方式打开 $this->firstip = $this->get4b(); //第一条ip索引的绝对偏移地址 $this->lastip = $this->get4b(); //最后一条ip索引的绝对偏移地址 $this->totalip =($this->lastip - $this->firstip)/7 ; //ip总数 索引区是定长的7个字节,在此要除以7, register_shutdown_function(array($this,"closefp")); //为了兼容php5以下版本,本类没有用析构函数,自动关闭ip库.}//*//关闭ip库//*function closefp(){fclose($this->fp);}//*//读取4个字节并将解压成long的长模式//*function get4b(){ $str=unpack("V",fread($this->fp,4)); return $str[1];}//*//读取重定向了的偏移地址//*function getoffset(){ $str=unpack("V",fread($this->fp,3).chr(0)); return $str[1];}//*//读取ip的详细地址信息//*function getstr(){ $str=""; $split=fread($this->fp,1); while (ord($split)!=0) { $str .=$split; $split=fread($this->fp,1); } return $str;}//*//将ip通过ip2long转成ipv4的互联网地址,再将他压缩成big-endian字节序//用来和索引区内的ip地址做比较//*function iptoint($ip){ return pack("N",intval(ip2long($ip)));}//*//获取客户端ip地址//注意:如果你想要把ip记录到服务器上,请在写库时先检查一下ip的数据是否安全.//*function getIP() { if (getenv('HTTP_CLIENT_IP')) { $ip = getenv('HTTP_CLIENT_IP'); } elseif (getenv('HTTP_X_FORWARDED_FOR')) { //获取客户端用代理服务器访问时的真实ip 地址 $ip = getenv('HTTP_X_FORWARDED_FOR'); } elseif (getenv('HTTP_X_FORWARDED')) { $ip = getenv('HTTP_X_FORWARDED'); } elseif (getenv('HTTP_FORWARDED_FOR')) { $ip = getenv('HTTP_FORWARDED_FOR'); } elseif (getenv('HTTP_FORWARDED')) { $ip = getenv('HTTP_FORWARDED'); } else { $ip = $_SERVER['REMOTE_ADDR']; } return $ip;}//*//获取地址信息//*function readaddress(){ $now_offset=ftell($this->fp); //得到当前的指针位址 $flag=$this->getflag(); switch (ord($flag)){ case 0: $address=""; break; case 1: case 2: fseek($this->fp,$this->getoffset()); $address=$this->getstr(); break; default: fseek($this->fp,$now_offset); $address=$this->getstr(); break; } return $address;}//*//获取标志1或2//用来确定地址是否重定向了.//*function getflag(){ return fread($this->fp,1);}//*//用二分查找法在索引区内搜索ip//*function searchip($ip){ $ip=gethostbyname($ip); //将域名转成ip $ip_offset["ip"]=$ip; $ip=$this->iptoint($ip); //将ip转换成长整型 $firstip=0; //搜索的上边界 $lastip=$this->totalip; //搜索的下边界 $ipoffset=$this->lastip; //初始化为最后一条ip地址的偏移地址 while ($firstip fp,$this->firstip + $i * 7); //定位指针到中间记录 $startip=strrev(fread($this->fp,4)); //读取当前索引区内的开始ip地址,并将其little-endian的字节序转换成big-endian的字节序 if ($ip fp,$this->getoffset()); $endip=strrev(fread($this->fp,4)); if ($ip > $endip){ $firstip=$i + 1; } else { $ip_offset["offset"]=$this->firstip + $i * 7; break; } } } return $ip_offset;}//*//获取ip地址详细信息//*function getaddress($ip){ $ip_offset=$this->searchip($ip); //获取ip 在索引区内的绝对编移地址 $ipoffset=$ip_offset["offset"]; $address["ip"]=$ip_offset["ip"]; fseek($this->fp,$ipoffset); //定位到索引区 $address["startip"]=long2ip($this->get4b()); //索引区内的开始ip 地址 $address_offset=$this->getoffset(); //获取索引区内ip在ip记录区内的偏移地址 fseek($this->fp,$address_offset); //定位到记录区内 $address["endip"]=long2ip($this->get4b()); //记录区内的结束ip 地址 $flag=$this->getflag(); //读取标志字节 switch (ord($flag)) { case 1: //地区1地区2都重定向 $address_offset=$this->getoffset(); //读取重定向地址 fseek($this->fp,$address_offset); //定位指针到重定向的地址 $flag=$this->getflag(); //读取标志字节 switch (ord($flag)) { case 2: //地区1又一次重定向, fseek($this->fp,$this->getoffset()); $address["area1"]=$this->getstr(); fseek($this->fp,$address_offset+4); //跳4个字节 $address["area2"]=$this->readaddress(); //地区2有可能重定向,有可能没有 break; default: //地区1,地区2都没有重定向 fseek($this->fp,$address_offset); //定位指针到重定向的地址 $address["area1"]=$this->getstr(); $address["area2"]=$this->readaddress(); break; } break; case 2: //地区1重定向 地区2没有重定向 $address1_offset=$this->getoffset(); //读取重定向地址 fseek($this->fp,$address1_offset); $address["area1"]=$this->getstr(); fseek($this->fp,$address_offset+8); $address["area2"]=$this->readaddress(); break; default: //地区1地区2都没有重定向 fseek($this->fp,$address_offset+4); $address["area1"]=$this->getstr(); $address["area2"]=$this->readaddress(); break; } //*过滤一些无用数据 if (strpos($address["area1"],"CZ88.NET")!=false){ $address["area1"]="未知"; } if (strpos($address["area2"],"CZ88.NET")!=false){ $address["area2"]=" "; } return $address; }}
?
?
mapService类,方法类
?
?
/** * Google Map Service * 2011.4.8 */import("ORG.IPA.IpLocation");class mapService{ public static function getIPaddress($ip){ //返回格式 $format = "text";//默认text,json,xml,js //返回编码 $charset = "utf8"; //默认utf-8,gbk或gb2312 $ip_l=new IpLocation(); $address=$ip_l->getaddress($ip); $address["area1"] = iconv('GB2312','utf-8',$address["area1"]); $address["area2"] = iconv('GB2312','utf-8',$address["area2"]); $add=$address["area1"].$address["area2"]; if($add=="本机地址 "){ $add="杭州"; } return $add; }}
然后就可以在登陆的Action接口函数中调用两个文件类了:
?
?
import("ORG.IPA.MapService"); $ipaddress = get_client_ip(); $adrInfo=MapService::getIPaddress($ipaddress);
?
接下去就可以将上述信息记录到数据库中了,而在用户进入地图页面便可以将数据从数据库导出,并发送到view层进行显示,并在前端层调用Google Map API
?
后台控制层代码很简单:
?
?
public function map(){ parent::islogin(); $model = D("Topicview"); $list = $model->field('id,tid,imgid,avatar,address,create_time,topic_from,content,nickname,rootid,homepage') ->where("Topic.status=1 and Topic.type='first'") ->order("id desc") ->find(); //dump($list); $this->assign('addrList',$list); parent::showSiteInfo("Lab前端实验室 - Map Position"); $this->display(); }
?
接下来是前台模板层js代码:
?
?
if (typeof flowg == "undefined" || !flowg) { var flowg = {};}flowg.initMap = (function(){ var htmlString = '<div style="overflow: auto;">' + '<div style="width:300px;overflow:hidden;" class="map-item">' + '<div class="map-left">' + '<img src="%7B:getUserAvatar(%24addrList%5B" avatar alt="{$addrList.nickname}" style="max-width:90%">' + '</div> <div class="map-right">' + '<div class="map-content">{$addrList.nickname} : {$addrList.content}</div>' + '<div class="time">他在{$addrList.address}</div>' + '</div>' + '</div>'; var geocoder; var map; var oldinfo = null; function initialize(){ geocoder = new google.maps.Geocoder(); var latlng = new google.maps.LatLng(34.016, 103.535); var myOptions = { zoom: 8, center: latlng, mapTypeId: google.maps.MapTypeId.ROADMAP }; map = new google.maps.Map(document.getElementById("map_canvas"), myOptions); codeAddress("{$addrList.address}", htmlString); } function codeAddress(address, html){ geocoder.geocode({ 'address': address }, function(results, status){ if (status == google.maps.GeocoderStatus.OK) { map.setCenter(results[0].geometry.location); var marker = new google.maps.Marker({ map: map, position: results[0].geometry.location }); var contentString = html; var infowindow = new google.maps.InfoWindow({ content: contentString }); infowindow.open(map, marker); if (oldinfo != null) { oldinfo.close(); } oldinfo = infowindow; } else { return false; } }); } return initialize; })();$(flowg.initMap);?<p>?</p> <p>上面直接调用了google map的marker功能对于信息进行展示,效果图:</p> <p>?</p> <p><br><img alt="" src="/img/2012/10/19/1332391838.png"></p> <div class="clear"> </div> </div>