1. 程式人生 > >基於PHP+MongoDB的LBS附近的人應用-初探

基於PHP+MongoDB的LBS附近的人應用-初探

<?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); }