基於PHP+MongoDB的LBS附近的人應用-初探
阿新 • • 發佈:2018-12-24
<?php
ini_set("display_errors", "On");
error_reporting(E_ALL | E_STRICT);
$mongo_config = [
'host'=>'127.0.0.1',
'port'=>27017,
'dbname'=>'my_app',
'user'=>'',
'pwd'=>''
];
$host_port = $mongo_config['host'] . ":" . $mongo_config['port'];
try {
$mongoDB = new MongoClient($host_port );
$mongo_model = $mongoDB->selectDB($mongo_config['dbname']);
} catch(\Exception $e) {
echo responseJson(0, 'MongoDB connection was fail.');
exit();
}
$lbs = new LBS();
$lbs->setKvDB($mongo_model);
$method = trim($_POST['method']);
switch($method) {
case 'join':
$longitude = $_POST['lng'];
$latitude = $_POST['lat'];
$uid = $_POST['uuid'];
$r = $lbs->geoAdd($longitude, $latitude, $uid);
if($r) {
$users = $lbs->geoSearch($longitude, $latitude);
if(!empty($users)) {
echo responseJson(1, '已經找到附近的小夥伴了.' , $users);
} else {
echo responseJson(0, '你附近沒有小夥伴.');
}
} else {
echo responseJson(0, '上報地理位置失敗');
exit();
}
break;
case 'search':
echo georadiusbymember($redis);
break;
default:
echo responseJson(0,'未知操作');
break;
}
class LBS
{
private $kvDB;
private $index_type = '2dsphere';
private $table_name = 'user_lbs';
/**
* 設定儲存媒介,限定 mongoDB,所有操作基於mongo
* @param object $mongoDB
*
*/
public function setKvDB(MongoDB $mongoDB) {
$this->kvDB = $mongoDB;
}
/**
* 設定 lbs 表名稱
* @param double $longitude 經度
* @param double $latitude 維度
* @param string/int $uid 使用者ID
* @param array $data 其他資料,k v 形式, example: $data = ['username' => 'kevin','geo' => 'center'];
*/
public function geoAdd($longitude, $latitude, $uid, $data = []) {
$d = [
'loc' => [
'type' => 'Point',
'coordinates' => [doubleval($longitude), doubleval($latitude)]
],
'uid' => $uid
];
if($this->checkData($data)) {
$d = array_merge($d, $data);
}
$collection = $this->kvDB->selectCollection($this->table_name);
//查詢 該uid 是否存在,存在則更新
//$collection->remove(['uid' => $uid], ['justOne' => true]); // test
$exist = $collection->findOne(['uid' => $uid]);
$collection->ensureIndex(['loc' => $this->index_type]);
if($exist) {
$r = $collection->update(['uid' => $uid], ['$set' => $d]);
} else {
$r = $collection->insert($d);
}
return (isset($r['ok']) && !empty($r['ok'])) ? true : false;
}
/**
* 根據 經緯度查詢附近人
* @param double $longitude 經度
* @param double $latitude 維度
* @param int $maxdistance 預設 2000 Mi(米)
* @param int $limit 預設拉取100
* @return array 附近的人集合
*/
public function geoSearch($longitude, $latitude, $maxdistance = 1000, $limit = 100) {
$coll = $this->kvDB->selectCollection($this->table_name);
$r = $this->kvDB->command(
[
'geoNear' => $this->table_name,
'near' => [ 'type' => 'Point','coordinates' =>[doubleval($longitude), doubleval($latitude)]],
'spherical' => true,
'maxDistance' => $maxdistance,
'num' => $limit,
]
);
if(isset($r['ok']) && !empty($r['ok'])) {
return $r['results'];
} else {
return false;
}
}
/**
* 安全監測 如需嚴格,則需要判斷經緯度在範圍
* @param array $data
* @return bool|array
*/
public function checkData($data) {
if(empty($data)) return false;
if(isset($data['loc'])) unset($data['loc']);
if(isset($data['uid'])) unset($data['uid']);
return $data;
}
/**
* 設定 lbs 表名稱
* @param string $table_name default value "user_lbs"
*
*/
public function setTableName($table_name) {
$this->table_name = $table_name;
}
/**
* 獲取 lbs 表名稱
* @return string table name
*/
public function getTableName()
{
return $this->table_name;
}
/**
* 返回json
* @param int $state 狀態
* @param string $message 訊息
* @param array $data 資料
* @return json string json 資料
*/
function responseJson($state = 0, $message = '', $data = null) {
$r['state'] = $state;
$r['message'] = $message;
if(!is_null($data)) {
$r['data'] = $data;
}
return json_encode($r);
}
}
/**
* 返回json
* @param int $state 狀態
* @param string $message 訊息
* @param array $data 資料
* @return json string json 資料
*/
function responseJson($state = 0, $message = '', $data = null) {
$r['state'] = $state;
$r['message'] = $message;
if(!is_null($data)) {
$r['data'] = $data;
}
return json_encode($r);
}