真实的国产乱ⅩXXX66竹夫人,五月香六月婷婷激情综合,亚洲日本VA一区二区三区,亚洲精品一区二区三区麻豆

成都創(chuàng)新互聯(lián)網(wǎng)站制作重慶分公司

如何使用PHP實(shí)現(xiàn)查找你想要的附近人

這篇文章主要介紹了如何使用PHP實(shí)現(xiàn)查找你想要的附近人,具有一定借鑒價(jià)值,需要的朋友可以參考下。希望大家閱讀完這篇文章后大有收獲。下面讓小編帶著大家一起了解一下。

創(chuàng)新互聯(lián)服務(wù)項(xiàng)目包括銅官網(wǎng)站建設(shè)、銅官網(wǎng)站制作、銅官網(wǎng)頁(yè)制作以及銅官網(wǎng)絡(luò)營(yíng)銷策劃等。多年來(lái),我們專注于互聯(lián)網(wǎng)行業(yè),利用自身積累的技術(shù)優(yōu)勢(shì)、行業(yè)經(jīng)驗(yàn)、深度合作伙伴關(guān)系等,向廣大中小型企業(yè)、政府機(jī)構(gòu)等提供互聯(lián)網(wǎng)行業(yè)的解決方案,銅官網(wǎng)站推廣取得了明顯的社會(huì)效益與經(jīng)濟(jì)效益。目前,我們服務(wù)的客戶以成都為中心已經(jīng)輻射到銅官省份的部分城市,未來(lái)相信會(huì)繼續(xù)擴(kuò)大服務(wù)區(qū)域并繼續(xù)獲得客戶的支持與信任!

LBS(基于位置的服務(wù))

查找附近的人有個(gè)更大的專有名詞叫做LBS(基于位置的服務(wù)),LBS是指是指通過(guò)電信移動(dòng)運(yùn)營(yíng)商的無(wú)線電通訊網(wǎng)絡(luò)或外部定位方式,獲取移動(dòng)終端用戶的位置信息,在GIS平臺(tái)的支持下,為用戶提供相應(yīng)服務(wù)的一種增值業(yè)務(wù)。因此首先得獲取用戶的位置,獲取用戶的位置有基于GPS、基于運(yùn)營(yíng)商基站、WIFI等方式,一般由客戶端獲取用戶位置的經(jīng)緯度坐標(biāo)上傳至應(yīng)用服務(wù)器,應(yīng)用服務(wù)器對(duì)用戶坐標(biāo)進(jìn)行保存,客戶端獲取附近的人數(shù)據(jù)的時(shí)候,應(yīng)用服務(wù)器基于請(qǐng)求人的地理位置配合一定的條件(距離,性別,活躍時(shí)間等)去數(shù)據(jù)庫(kù)進(jìn)行篩選和排序。

根據(jù)經(jīng)緯度如何得出兩點(diǎn)之間的距離?

我們都知道平面坐標(biāo)內(nèi)的兩點(diǎn)坐標(biāo)可以使用平面坐標(biāo)距離公式來(lái)計(jì)算,但經(jīng)緯度是利用三度空間的球面來(lái)定義地球上的空間的球面坐標(biāo)系統(tǒng),假定地球是正球體,關(guān)于球面距離計(jì)算公式如下:

如何使用PHP實(shí)現(xiàn)查找你想要的附近人

具體推斷過(guò)程有興趣的推薦這篇文章:【數(shù)學(xué)公式及推導(dǎo)】根據(jù)經(jīng)緯度計(jì)算地面兩點(diǎn)間的距離

PHP函數(shù)代碼如下:

/**
     * 根據(jù)兩點(diǎn)間的經(jīng)緯度計(jì)算距離
     * @param $lat1
     * @param $lng1
     * @param $lat2
     * @param $lng2
     * @return float
     */
    public static function getDistance($lat1, $lng1, $lat2, $lng2){
        $earthRadius = 6367000; //approximate radius of earth in meters
        $lat1 = ($lat1 * pi() ) / 180;
        $lng1 = ($lng1 * pi() ) / 180;
        $lat2 = ($lat2 * pi() ) / 180;
        $lng2 = ($lng2 * pi() ) / 180;
        $calcLongitude = $lng2 - $lng1;
        $calcLatitude = $lat2 - $lat1;
        $stepOne = pow(sin($calcLatitude / 2), 2) + cos($lat1) * cos($lat2) * pow(sin($calcLongitude / 2), 2);
        $stepTwo = 2 * asin(min(1, sqrt($stepOne)));
        $calculatedDistance = $earthRadius * $stepTwo;
        return round($calculatedDistance);
    }

MySQL代碼如下:

SELECT  
  id, (  
    3959 * acos (  
      cos ( radians(78.3232) )  
      * cos( radians( lat ) )  
      * cos( radians( lng ) - radians(65.3234) )  
      + sin ( radians(78.3232) )  
      * sin( radians( lat ) )  
    )  
  ) AS distance  
FROM markers  
HAVING distance < 30  
ORDER BY distance  
LIMIT 0 , 20;

除了上面通過(guò)計(jì)算球面距離公式來(lái)獲取,我們可以使用某些數(shù)據(jù)庫(kù)服務(wù)得到,比如redis和MongoDB:

Redis 3.2提供GEO地理位置功能,不僅可以獲取兩個(gè)位置之間的距離,獲取指定位置范圍內(nèi)的地理信息位置集合也很簡(jiǎn)單。Redis命令文檔

1.增加地理位置

GEOADD key longitude latitude member [longitude latitude member ...]

2.獲取地理位置

GEOPOS key member [member ...]

3.獲取兩個(gè)地理位置的距離

GEODIST key member1 member2 [unit]

4.獲取指定經(jīng)緯度的地理信息位置集合

GEORADIUS key longitude latitude radius m|km|ft|mi [WITHCOORD] [WITHDIST] [WITHHASH] [COUNT count] [ASC|DESC] [STORE key] [STOREDIST key]

5.獲取指定成員的地理信息位置集合

GEORADIUSBYMEMBER key member radius m|km|ft|mi [WITHCOORD] [WITHDIST] [WITHHASH] [COUNT count] [ASC|DESC] [STORE key] [STOREDIST key]

MongoDB專門針對(duì)這種查詢建立了地理空間索引。 2d和2dsphere索引,分別是針對(duì)平面和球面。 MongoDB文檔

1.添加數(shù)據(jù)

db.location.insert( {uin : 1 , loc : { lon : 50 , lat : 50 } } )

2.建立索引

db.location.ensureIndex( { loc : "2d" } )

3.查找附近的點(diǎn)

db.location.find( { loc :{ $near : [50, 50] } )

4.最大距離和限制條數(shù)

db.location.find( { loc : { $near : [50, 50] , $maxDistance : 5 } } ).limit(20)

5.使用geoNear在查詢結(jié)果中返回每個(gè)點(diǎn)距離查詢點(diǎn)的距離

db.runCommand( { geoNear : "location" , near : [ 50 , 50 ], num : 10, query : { type : "museum" } } )

6.使用geoNear附帶查詢條件和返回條數(shù),geoNear使用runCommand命令不支持find查詢中分頁(yè)相關(guān)limit和skip參數(shù)的功能

db.runCommand( { geoNear : "location" , near : [ 50 , 50 ], num : 10, query : { uin : 1 } })

PHP多種方式和具體實(shí)現(xiàn)

1.基于MySql

成員添加方法:

public function geoAdd($uin, $lon, $lat)
{
    $pdo = $this->getPdo();
    $sql = 'INSERT INTO `markers`(`uin`, `lon`, `lat`) VALUES (?, ?, ?)';
    $stmt = $pdo->prepare($sql);
    return $stmt->execute(array($uin, $lon, $lat));
}

查詢附近的人(支持查詢條件和分頁(yè)):

public function geoNearFind($lon, $lat, $maxDistance = 0, $where = array(), $page = 0)
{
    $pdo = $this->getPdo();
    $sql = "SELECT  
              id, (  
                3959 * acos (  
                  cos ( radians(:lat) )  
                  * cos( radians( lat ) )  
                  * cos( radians( lon ) - radians(:lon) )  
                  + sin ( radians(:lat) )  
                  * sin( radians( lat ) )  
                )  
              ) AS distance  
            FROM markers";

    $input[':lat'] = $lat;
    $input[':lon'] = $lon;

    if ($where) {
        $sqlWhere = ' WHERE ';
        foreach ($where as $key => $value) {
            $sqlWhere .= "`{$key}` = :{$key} ,";
            $input[":{$key}"] = $value;
        }
        $sql .= rtrim($sqlWhere, ',');
    }

    if ($maxDistance) {
        $sqlHaving = " HAVING distance < :maxDistance";
        $sql .= $sqlHaving;
        $input[':maxDistance'] = $maxDistance;
    }

    $sql .= ' ORDER BY distance';

    if ($page) {
        $page > 1 ? $offset = ($page - 1) * $this->pageCount : $offset = 0;
        $sqlLimit = " LIMIT {$offset} , {$this->pageCount}";
        $sql .= $sqlLimit;
    }

    $stmt = $pdo->prepare($sql);
    $stmt->execute($input);
    $list = $stmt->fetchAll(PDO::FETCH_ASSOC);

    return $list;
}

2.基于Redis(3.2以上)

PHP使用Redis可以安裝redis擴(kuò)展或者通過(guò)composer安裝predis類庫(kù),本文使用redis擴(kuò)展來(lái)實(shí)現(xiàn)。

成員添加方法:

public function geoAdd($uin, $lon, $lat)
{
    $redis = $this->getRedis();
    $redis->geoAdd('markers', $lon, $lat, $uin);
    return true;
}

查詢附近的人(不支持查詢條件和分頁(yè)):

public function geoNearFind($uin, $maxDistance = 0, $unit = 'km')
{
    $redis = $this->getRedis();
    $options = ['WITHDIST']; //顯示距離
    $list = $redis->geoRadiusByMember('markers', $uin, $maxDistance, $unit, $options);
    return $list;
}

3.基于MongoDB

PHP使用MongoDB的擴(kuò)展有mongo(文檔)和mongodb(文檔),兩者寫法差別很大,選擇好擴(kuò)展需要對(duì)應(yīng)相應(yīng)的文檔查看,由于mongodb擴(kuò)展是新版,本文選擇mongodb擴(kuò)展。

假設(shè)我們創(chuàng)建db庫(kù)和location集合

設(shè)置索引:

db.getCollection('location').ensureIndex({"uin":1},{"unique":true}) 
db.getCollection('location').ensureIndex({loc:"2d"})
#若查詢位置附帶查詢,可以將常查詢條件添加至組合索引
#db.getCollection('location').ensureIndex({loc:"2d",uin:1})

成員添加方法:

public function geoAdd($uin, $lon, $lat)
{
    $document = array(
        'uin' => $uin,
        'loc' => array(
            'lon' =>  $lon,
            'lat' =>  $lat,
        ),
    );

    $bulk = new MongoDB\Driver\BulkWrite;
    $bulk->update(
        ['uin' => $uin],
        $document,
        [ 'upsert' => true]
    );
    //出現(xiàn)noreply 可以改成確認(rèn)式寫入
    $manager = $this->getMongoManager();
    $writeConcern = new MongoDB\Driver\WriteConcern(1, 100);
    //$writeConcern = new MongoDB\Driver\WriteConcern(MongoDB\Driver\WriteConcern::MAJORITY, 100);
    $result = $manager->executeBulkWrite('db.location', $bulk, $writeConcern);

    if ($result->getWriteErrors()) {
        return false;
    }
    return true;
}

查詢附近的人(返回結(jié)果沒(méi)有距離,支持查詢條件,支持分頁(yè))

public function geoNearFind($lon, $lat, $maxDistance = 0, $where = array(), $page = 0)
{
    $filter = array(
        'loc' => array(
            '$near' => array($lon, $lat),
        ),
    );
    if ($maxDistance) {
        $filter['loc']['$maxDistance'] = $maxDistance;
    }
    if ($where) {
        $filter = array_merge($filter, $where);
    }
    $options = array();
    if ($page) {
        $page > 1 ? $skip = ($page - 1) * $this->pageCount : $skip = 0;
        $options = [
            'limit' => $this->pageCount,
            'skip' => $skip
        ];
    }

    $query = new MongoDB\Driver\Query($filter, $options);
    $manager = $this->getMongoManager();
    $cursor = $manager->executeQuery('db.location', $query);
    $list = $cursor->toArray();
    return $list;
}

查詢附近的人(返回結(jié)果帶距離,支持查詢條件,支付返回?cái)?shù)量,不支持分頁(yè)):

public function geoNearFindReturnDistance($lon, $lat, $maxDistance = 0, $where = array(), $num = 0)
{
    $params = array(
        'geoNear' => "location",
        'near' => array($lon, $lat),
        'spherical' => true, // spherical設(shè)為false(默認(rèn)),dis的單位與坐標(biāo)的單位保持一致,spherical設(shè)為true,dis的單位是弧度
        'distanceMultiplier' => 6371, // 計(jì)算成公里,坐標(biāo)單位distanceMultiplier: 111。 弧度單位 distanceMultiplier: 6371
    );

    if ($maxDistance) {
        $params['maxDistance'] = $maxDistance;
    }
    if ($num) {
        $params['num'] = $num;
    }
    if ($where) {
        $params['query'] = $where;
    }

    $command = new MongoDB\Driver\Command($params);
    $manager = $this->getMongoManager();
    $cursor = $manager->executeCommand('db', $command);
    $response = (array) $cursor->toArray()[0];
    $list = $response['results'];
    return $list;
}

注意事項(xiàng):

1.選擇好擴(kuò)展,mongo和mongodb擴(kuò)展寫法差別很大

2.寫數(shù)據(jù)時(shí)出現(xiàn)noreply請(qǐng)檢查寫入確認(rèn)級(jí)別

3.使用find查詢的數(shù)據(jù)需要自己計(jì)算距離,使用geoNear查詢的不支持分頁(yè)

4.使用geoNear查詢的距離需要轉(zhuǎn)化成km使用spherical和distanceMultiplier參數(shù)

感謝你能夠認(rèn)真閱讀完這篇文章,希望小編分享如何使用PHP實(shí)現(xiàn)查找你想要的附近人內(nèi)容對(duì)大家有幫助,同時(shí)也希望大家多多支持創(chuàng)新互聯(lián),關(guān)注創(chuàng)新互聯(lián)行業(yè)資訊頻道,遇到問(wèn)題就找創(chuàng)新互聯(lián),詳細(xì)的解決方法等著你來(lái)學(xué)習(xí)!


分享標(biāo)題:如何使用PHP實(shí)現(xiàn)查找你想要的附近人
瀏覽地址:http://weahome.cn/article/ppseis.html

其他資訊

在線咨詢

微信咨詢

電話咨詢

028-86922220(工作日)

18980820575(7×24)

提交需求

返回頂部