当前位置: 代码迷 >> PHP >> Google Map API 结合PHP实现登录map定位
  详细解决方案

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

热度:90   发布时间:2016-04-28 23:11:55.0
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 <= $lastip){    $i=floor(($firstip + $lastip) / 2);          //计算近似中间记录 floor函数记算给定浮点数小的最大整数,说白了就是四舍五也舍	fseek($this->fp,$this->firstip + $i * 7);    //定位指针到中间记录	$startip=strrev(fread($this->fp,4));         //读取当前索引区内的开始ip地址,并将其little-endian的字节序转换成big-endian的字节序	if ($ip < $startip) {	   $lastip=$i - 1;	}	else {	   fseek($this->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="{:getUserAvatar($addrList["avatar"],50)}" alt="{$addrList.nickname}" style="border:1px solid #ccc;padding:1px;">' +    '</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);
?

?

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

?


  相关解决方案