PHP安裝GeoIP擴(kuò)展根據(jù)IP獲取地理位置及計(jì)算距離的方法
根據(jù)IP獲取訪客所在國(guó)家/城市/經(jīng)緯度
安裝GeoIP擴(kuò)展:
sudo apt-get install libgeoip-dev
pecl install geoip-1.1.0
注意:Beta版要指定版本號(hào).如果是apt安裝的PHP,直接安裝php5-geoip這個(gè)包即可.
php.ini中加入:
extension=geoip.so geoip.custom_directory="/usr/share/GeoIP"
免費(fèi)下載GeoLiteCity數(shù)據(jù)庫(kù)(解壓后18MB):
http://dev.maxmind.com/geoip/legacy/install/city/
wget http://geolite.maxmind.com/download/geoip/database/GeoLiteCity.dat.gz gunzip GeoLiteCity.dat.gz sudo mkdir -v /usr/share/GeoIP sudo mv -v GeoLiteCity.dat /usr/share/GeoIP/GeoIPCity.dat
測(cè)試:
php -a
<?php
print_r(geoip_record_by_name('106.37.165.80')); //回車后按Ctrl+D運(yùn)行
Array
(
[continent_code] => AS
[country_code] => CN
[country_code3] => CHN
[country_name] => China //國(guó)家
[region] => 22
[city] => Beijing //城市
[postal_code] =>
[latitude] => 39.928901672363 //緯度
[longitude] => 116.38829803467 //經(jīng)度
[dma_code] => 0
[area_code] => 0
)
在命令行用geoiplookup查看IP信息:
traceroute www.oschina.net
可見(jiàn)IP地址
61.145.122.155
sudo apt-get install geoip-bin geoip-database geoiplookup 61.145.122.155 -f /usr/share/GeoIP/GeoIP.dat GeoIP Country Edition: CN, China
geoip-database提供的GeoIP.dat只能精確到國(guó)家.
geoiplookup 61.145.122.155 -f /usr/share/GeoIP/GeoIPCity.dat GeoIP City Edition, Rev 1: CN, 30, Guangdong, Guangzhou, N/A, 23.116699, 113.250000, 0, 0
從maxmind官網(wǎng)下的數(shù)據(jù)庫(kù)GeoLiteCity則信息更詳細(xì).
geoiplookup 61.145.122.155 則同時(shí)顯示上述兩個(gè)數(shù)據(jù)庫(kù)的信息.
根據(jù)IP確定經(jīng)緯度與計(jì)算距離
可以用
geoip_record_by_name($_SERVER['REMOTE_ADDR'])
根據(jù)用戶IP確定經(jīng)緯度.
注意:
geoip_record_by_name()
返回的西經(jīng)和南緯是負(fù)數(shù).
5000米轉(zhuǎn)成經(jīng)緯度:
緯度 Latitude: 1 deg = 110852 m
經(jīng)度 Longitude: 1 deg = 111320*cos(lat) m
同一經(jīng)線上,相差一緯度約為 110852 米
同一緯線上,相差一經(jīng)度約為 111320*cos(lat) 米 (lat為該緯線的緯度)
<?php //以當(dāng)前用戶經(jīng)緯度為中心,查詢5000米內(nèi)的其他用戶 $y = 5000 / 110852; //緯度的范圍 $x = 5000 / (111320*cos($lat)); //經(jīng)度的范圍 $sql = ' select * from user where lat >= ($lat-$y) and lat <= ($lat+$y) and lon >= ($lon-$x) and lon <= ($lon+$x); ';
數(shù)據(jù)庫(kù)用戶表中設(shè)兩個(gè)字段,分別存儲(chǔ)用戶的經(jīng)度lat和緯度lon.
($lat-$y) <= lat <= ($lat+$y) ($lon-$x) <= lon <= ($lon+$x)
這個(gè)范圍是一個(gè)粗略的范圍,下面計(jì)算距離后把超過(guò)5公里的用戶去掉即可.
根據(jù)上面查詢出來(lái)的用戶的經(jīng)緯度,
用半正矢公式(Haversine)根據(jù)經(jīng)緯度計(jì)算兩點(diǎn)間距離:
<?php
function distance($lat1, $lon1, $lat2, $lon2) {
$R = 6371393; //地球平均半徑,單位米
$dlat = deg2rad($lat2-$lat1);
$dlon = deg2rad($lon2-$lon1);
$a = pow(sin($dlat/2), 2) + cos(deg2rad($lat1)) * cos(deg2rad($lat2)) * pow(sin($dlon/2), 2);
$c = 2 * atan2(sqrt($a), sqrt(1-$a));
$d = $R * $c;
return round($d);
}
echo distance(0, 0, -1, 0); // 111202米
然后就可以用uasort或array_multisort由近到遠(yuǎn)列出用戶了,比如有名為win,osx,lin這3個(gè)用戶:
<?php
$arr = array(
'win' => array(
'dis' => 1024,
'age' => 31
),
'osx' => array(
'dis' => 512,
'age' => 15
),
'lin' => array(
'dis' => 512,
'age' => 25
)
);
foreach($arr as $k => $v) {
$sort['dis'][$k] = $v['dis'];
$sort['age'][$k] = $v['age'];
}
//先按距離升序排序,如果距離相同,則按年齡降序排序
array_multisort($sort['dis'], SORT_ASC, $sort['age'], SORT_DESC, $arr);
echo json_encode($arr);
//{"lin":{"dis":512,"age":25},"osx":{"dis":512,"age":15},"win":{"dis":1024,"age":31}}
相關(guān)文章
PHP時(shí)間戳 strtotime()使用方法和技巧
php strtotime()解釋如何使用,看了下面的文章就要以學(xué)習(xí)到了。下面還有php文檔函數(shù)解釋。2013-10-10
分享微信掃碼支付開(kāi)發(fā)遇到問(wèn)題及解決方案-附Ecshop微信支付插件
微信掃碼支付在購(gòu)物商城非常流行,本篇文章給大家分享微信掃碼支付開(kāi)發(fā)遇到問(wèn)題及解決方案-附Ecshop微信支付插件,需要的朋友可以參考下2015-08-08
Laravel數(shù)據(jù)庫(kù)讀寫(xiě)分離配置的方法
今天小編就為大家分享一篇Laravel數(shù)據(jù)庫(kù)讀寫(xiě)分離配置的方法,具有很好的參考價(jià)值,希望對(duì)大家有所幫助。一起跟隨小編過(guò)來(lái)看看吧2019-10-10
PHP未登錄自動(dòng)跳轉(zhuǎn)到登錄頁(yè)面
為了滿足用戶體驗(yàn)度,需要用戶登錄才能跳轉(zhuǎn)到頁(yè)面,這篇文章給大家分享PHP未登錄自動(dòng)跳轉(zhuǎn)到登錄頁(yè)面的實(shí)例代碼,需要的朋友參考下2016-12-12
php array_walk 對(duì)數(shù)組中的每個(gè)元素應(yīng)用用戶自定義函數(shù)詳解
php array_walk函數(shù)將用戶自定義函數(shù)應(yīng)用到 array 數(shù)組中的每個(gè)單元,即使用用戶自定義函數(shù)對(duì)數(shù)組中的每個(gè)元素做回調(diào)處理。 本文章向大家講解array_walk函數(shù)的基本語(yǔ)法及使用實(shí)例,需要的朋友可以參考下2016-11-11
php上傳apk后自動(dòng)提取apk包信息的使用(示例下載)
本篇文章介紹了,php上傳apk后自動(dòng)提取apk包信息的使用(示例下載)需要的朋友參考下2013-04-04

