웹 추적 매직
PHP 및 Javascript로 GPS 추적 시스템을 만드는 방법에 대한 자습서를 시작합니다. 한때 인터넷의 어두운 시대에 GPS는 거의 알려지지 않았으며 사람들은 실제로 그것에 대해 크게 신경 쓰지 않았습니다. 일부 스마트 원숭이는 스마트 폰 (및 스마트 폰 내부의 GPS 장치)이 발명 되기 전까지는 그것이 얼마나 유용한 지 깨달았습니다.
차량이 있는 위치, 다음 버스가 올 때, 순서가 어디인지 또는 사람들이 실제로 올바른 장소로 배달했는지 확인합니다. 가능성은 무한하며, 기본 앱에만 국한된 것이 아니라 PHP와 Javascript를 사용하여 웹앱을 만들 수도 있습니다. 방법을 알아 보려면 계속 읽으십시오.
ⓘ이 튜토리얼의 시작 부분에 모든 소스 코드가 포함 된 zip 파일이 포함되어 있으므로 모든 것을 복사하여 붙여 넣을 필요가 없습니다.
소스 코드 다운로드
먼저 약속 한대로 소스 코드에 대한 다운로드 링크가 있습니다.
소스 코드 다운로드
소스 코드를 다운로드하려면 여기를 클릭하십시오. MIT 라이센스에 따라 릴리스되었으므로 그 위에 빌드하거나 자신의 프로젝트에서 자유롭게 사용하십시오.
폴더
다음은 zip 파일에서 폴더를 구성하는 방법에 대한 간략한 소개입니다.
빠른 참고 사항
지도 통합은 어디에 있습니까?
“지도 통합에 도움이 필요합니다”에 대한 의견이 너무 많습니다. 그러나 이 튜토리얼에서는 지도 통합이 아닌 "기술 GPS 부분"만 다룹니다. 왜?
즉,이 학습서에서 모든 맵 서비스를 다루는 것은 불가능합니다. 모든 사람을 하나씩 도울 수는 없습니다. 지도 통합에 대한 귀하의 질문을 승인하거나 답변하지 않으면 죄송합니다. 나는 단지 무료로 프로젝트와 상담을 할 수 없으며, 이것은 당신의 숙제입니다.
개요 및 가정
코드에 들어가기 전에 길을 잃지 않도록 전체 시스템에 대한 개요부터 시작하겠습니다. 또한 이 안내서에서 무엇을 기대 해야 하는지에 대한 일부 가정.
시스템 개요
GPS 추적 시스템을 사용하는 방법에는 여러 가지가 있으며,이 안내서는 이를 사용하는 가장 일반적인 방법 중 하나 인 다양한 배송 라이더 추적을 안내합니다. 우리는 통제 괴물이 되기를 원하기 때문이 아니라 고객에게 주문 위치를 알려주고 마일리지에 대한 라이더의 보상을 적절하게 하기 위해서입니다. 이 시스템에는 4 가지 부품이 있습니다.
가정
여러분 중 일부는 이미 기존 프로젝트를 가지고 있어야 하므로 여기서는 다른 사용자 시스템이나 관리자 패널을 다시 만들지 않을 것입니다. 이 가이드는 순전히 GPS 추적에만 적용됩니다. 또한 이것은 웹 기술에서 가능한 것을 보여주는 베어 본 시스템이 될 것입니다 – 유료 프로젝트를 수행하는 사람들에게는 무료 점심이 제공되지 않습니다. ?
또한 여러분 대부분은 이미 PHP, HTML, CSS, Javascript, AJAX, JSON 및 모든 개념에 익숙한 충분한 코드 사용자라고 가정합니다. 우리는 이 안내서의“GPS 란 무엇인가”와 같은 아주 지루한 작은 세부 사항에 대해서는 다루지 않을 것입니다.
데이터베이스
이제 우리는 시스템의 개요를 다 끝냈으니, 기초 (데이터베이스)를 놓음으로써 시스템 구축을 시작하겠습니다.
마지막으로 알려진 위치
CREATE TABLE `gps_track` ( `rider_id` int(11) NOT NULL, `track_time` datetime NOT NULL DEFAULT CURRENT_TIMESTAMP, `track_lng` decimal(11,7) NOT NULL, `track_lat` decimal(11,7) NOT NULL ) ENGINE=InnoDB DEFAULT CHARSET=latin1; ALTER TABLE `gps_track` ADD PRIMARY KEY (`rider_id`), ADD KEY `track_time` (`track_time`); COMMIT;
Field | Description |
rider_id | Primary key, the rider ID. This could also be the ID of whatever you want to track. |
track_time | Time the rider last “checked in”. |
track_lng | Longitude. |
track_lat | Latitude. |
그렇습니다. 라이더의 마지막 위치를 저장하는 데 필요한 전부입니다.
RIDER TABLE
CREATE TABLE `riders` ( `rider_id` int(11) NOT NULL, `rider_name` varchar(255) NOT NULL, `rider_tel` varchar(64) NOT NULL, `rider_email` varchar(255) NOT NULL ) ENGINE=InnoDB DEFAULT CHARSET=latin1; ALTER TABLE `riders` ADD PRIMARY KEY (`rider_id`), ADD UNIQUE KEY `rider_email` (`rider_email`); ALTER TABLE `riders` MODIFY `rider_id` int(11) NOT NULL AUTO_INCREMENT; COMMIT;
이것은 시스템에서 정확하게 사용되지 않습니다. 그러나 이 튜토리얼의 완성을 위해 여기에 보유 할 수 있는 라이더 데이터베이스의 예가 있습니다.
Field | Description |
rider_id | Primary key and auto-increment, The rider ID. |
rider_name | The rider’s name. |
rider_tel | The rider’s telephone number. |
rider_email | The rider’s email address. |
ENDPOINT
다음으로, 우리는 또 다른 기초를 세울 것입니다 – GPS 좌표를 받고 서비스 할 GPS 추적 시스템의 끝점.
구성 파일
// MUTE NOTICES error_reporting(E_ALL & ~E_NOTICE); // DATABASE SETTINGS - CHANGE THESE TO YOUR OWN define('DB_HOST', 'localhost'); define('DB_NAME', 'test'); define('DB_CHARSET', 'utf8'); define('DB_USER', 'root'); define('DB_PASSWORD', ''); // AUTO FILE PATH define('PATH_LIB', __DIR__ . DIRECTORY_SEPARATOR);
우리가 만들 첫 번째 스크립트는 모든 설정을 넣을 수 있는 구성 파일입니다. 데이터베이스 설정을 원하는 대로 변경하십시오.
GPS TRACKING LIBRARY
class Track { /* [DATABASE HELPER FUNCTIONS] */ protected $pdo = null; protected $stmt = null; public $lastID = null; function __construct () { // __construct() : connect to the database // PARAM : DB_HOST, DB_CHARSET, DB_NAME, DB_USER, DB_PASSWORD // ATTEMPT CONNECT try { $str = "mysql:host=" . DB_HOST . ";charset=" . DB_CHARSET; if (defined('DB_NAME')) { $str .= ";dbname=" . DB_NAME; } $this->pdo = new PDO( $str, DB_USER, DB_PASSWORD, [ PDO::ATTR_ERRMODE => PDO::ERRMODE_EXCEPTION, PDO::ATTR_DEFAULT_FETCH_MODE => PDO::FETCH_ASSOC, PDO::ATTR_EMULATE_PREPARES => false ] ); } // ERROR - CRITICAL STOP - THROW ERROR MESSAGE catch (Exception $ex) { print_r($ex); die(); } } function __destruct () { // __destruct() : close connection when done if ($this->stmt !== null) { $this->stmt = null; } if ($this->pdo !== null) { $this->pdo = null; } } function exec ($sql, $data=null) { // exec() : run insert, replace, update, delete query // PARAM $sql : SQL query // $data : array of data try { $this->stmt = $this->pdo->prepare($sql); $this->stmt->execute($data); $this->lastID = $this->pdo->lastInsertId(); } catch (Exception $ex) { $this->error = $ex; return false; } $this->stmt = null; return true; } function fetchAll ($sql, $cond=null, $key=null, $value=null) { // fetchAll() : perform select query (multiple rows expected) // PARAM $sql : SQL query // $cond : array of conditions // $key : sort in this $key=>data order, optional // $value : $key must be provided. If string provided, sort in $key=>$value order. If function provided, will be a custom sort. $result = []; try { $this->stmt = $this->pdo->prepare($sql); $this->stmt->execute($cond); // Sort in given order if (isset($key)) { if (isset($value)) { if (is_callable($value)) { while ($row = $this->stmt->fetch(PDO::FETCH_NAMED)) { $result[$row[$key]] = $value($row); } } else { while ($row = $this->stmt->fetch(PDO::FETCH_NAMED)) { $result[$row[$key]] = $row[$value]; } } } else { while ($row = $this->stmt->fetch(PDO::FETCH_NAMED)) { $result[$row[$key]] = $row; } } } // No key-value sort order else { $result = $this->stmt->fetchAll(); } } catch (Exception $ex) { $this->error = $ex; return false; } // Return result $this->stmt = null; return count($result)==0 ? false : $result ; } function fetch ($sql, $cond=null, $sort=null) { // fetch() : perform select query (single row expected) // returns an array of column => value // PARAM $sql : SQL query // $cond : array of conditions // $sort : custom sort function $result = []; try { $this->stmt = $this->pdo->prepare($sql); $this->stmt->execute($cond); if (is_callable($sort)) { while ($row = $this->stmt->fetch(PDO::FETCH_NAMED)) { $result = $sort($row); } } else { while ($row = $this->stmt->fetch(PDO::FETCH_NAMED)) { $result = $row; } } } catch (Exception $ex) { $this->error = $ex; return false; } // Return result $this->stmt = null; return count($result)==0 ? false : $result ; } /* [TRACKING FUNCTIONS] */ function update ($id, $lng, $lat) { // update() : update rider coordinates // PARAM $id : rider ID // $lng : longitude // $lat : latitude return $this->exec( "REPLACE INTO `gps_track` (`rider_id`, `track_time`, `track_lng`, `track_lat`) VALUES (?, ?, ?, ?)", [$id, date("Y-m-d H:i:s"), $lng, $lat] ); } function get ($id) { // get() : get rider coordinates // PARAM $id : rider ID return $this->fetch( "SELECT * FROM `gps_track` WHERE `rider_id`=?", [$id] ); } function getAll () { // getAll() : get all the rider locations // !! You might want to implement an "on active duty" flag in your own system // !! Just so that only the relevant riders are extracted return $this->fetchAll( "SELECT * FROM `gps_track`", null, "rider_id" ); } }
처음에는 위협적인 것처럼 보이지만 차분하고 분석하십시오. 추적 라이브러리에는 2 개의 부품 만 있습니다.
Function | Description |
__construct | The constructor, automatically connects to the database when the object is created. |
__destruct | The destructor, automatically closes the database connection when the object is destroyed. |
exec | Runs a single insert, replace, update, or delete query. |
fetchAll | Run a select query. Returns an associative array of with multiple rows of results. |
fetch | Run a select query. Returns an associative array of column > value. |
Function | Description |
update | Update the location of the given rider. |
get | Get the last known location of the given rider. |
getAll | Get all rider locations. |
AJAX HANDLER (OR ENDPOINT)
// INIT require __DIR__ . DIRECTORY_SEPARATOR . "lib" . DIRECTORY_SEPARATOR . "2a-config.php"; require PATH_LIB . "2b-lib-track.php"; $trackLib = new Track(); // HANDLE REQUESTS // !! You might want to restrict access // !! Implement your own user sessions and security checks switch ($_POST['req']) { // INVALID REQUEST default: echo json_encode([ "status" => 0, "message" => "Invalid request" ]); break; // UPDATE RIDER LOCATION case "update": $pass = $trackLib->update($_POST['rider_id'], $_POST['lng'], $_POST['lat']); echo json_encode([ "status" => $pass ? 1 : 0, "message" => $pass ? "OK" : $trackLib->error ]); break; // GET RIDER LOCATION case "get": $location = $trackLib->get($_POST['rider_id']); echo json_encode([ "status" => is_array($location) ? 1 : 0, "message" => $location ]); break; // GET ALL RIDER LOCATIONS case "getAll": $location = $trackLib->getAll(); echo json_encode([ "status" => is_array($location) ? 1 : 0, "message" => $location ]); break; }
마지막으로 실제 엔드 포인트는 이전에 만든 라이브러리를 사용합니다. 작동 방식은 매우 간단합니다. 필요한 것을 지정하기 위해 $_POST['req'] 만 전달하면 되고 필요한 매개 변수가 뒤 따릅니다.
Request | Description |
update | Update the location of the given rider. Parameters:
|
get | Get the last known location of a given rider. Parameters:
|
getAll | Get all the last-known locations of the riders. |
TRACKER
이제 모든 기초가 준비되었으므로 라이더의 현재 위치 서버를 업데이트 할 간단한 추적기를 만들어야 합니다.
THE TRACKER SCRIPT
<html> <head> <title> Javascript Geolocation Tracking Demo </title> <script> var track = { display : null, // Holder for the <p> element, for visual feedback rider : 999, // Rider ID - Hardcode this somewhere in your own system session or in the web app delay : 20000, // Delay in between each position update, in milliseconds timer : null, // Holder for the interval object update : function () { // track.update() : update server of current location navigator.geolocation.getCurrentPosition(function (pos) { // AJAX DATA var data = new FormData(); data.append('req', 'update'); data.append('rider_id', track.rider); data.append('lat', pos.coords.latitude); data.append('lng', pos.coords.longitude); // AJAX var xhr = new XMLHttpRequest(); xhr.open('POST', "2c-ajax-track.php", true); xhr.onload = function () { var res = JSON.parse(this.response); // OK if (res.status==1) { track.display.innerHTML = "Lat: " + pos.coords.latitude + " Lng: " + pos.coords.longitude; } // ERROR else { track.display.innerHTML = res.message; } }; xhr.send(data); }); } }; // INIT ON PAGE LOAD window.addEventListener("load", function(){ track.display = document.getElementById("display"); if (navigator.geolocation) { // Set on an interval so that you don't drain the smartphone battery // Nor kill the server for the matter track.update(); setInterval(track.update, track.delay); } else { track.display.innerHTML = "Geolocation is not supported by your browser!"; } }); </script> </head> <body> <p id="display"></p> <p> This is a demo tracking page. You will normally create a rider login page, or convert this into a webapp. For those who do not know - Check out Apache Cordova and Ionic. </p> </body> </html>
그렇습니다, 그것은 그것의 요지입니다. 물론, 실제 프로젝트에서는 적절한 로그인 시스템을 보유하고 라이더를 식별해야 합니다. 또는 Android / iOS 앱을 생성 할 수 있는 옵션이 항상 있습니다.
ADMIN
퍼즐의 마지막 조각은 라이더의 위치를 추출하여 지도에 표시하는 관리자 페이지를 만드는 것입니다.
중앙 제어
<html> <head> <title> PHP Javascript Tracking Demo </title> <style> #map { width: 100%; height: 300px; background: #f2f2f2; } </style> <script> var track = { map : null, // Holder for HTML map element delay : 50000, // Delay in between each location refresh show : function () { // track.show() : get location data from server and update map // Sadly, Google Maps API is not free. // Check out more on their website if you want to use their maps on your app. // https://developers.google.com/maps/documentation/ // AJAX DATA var data = new FormData(); data.append('req', 'getAll'); // AJAX var xhr = new XMLHttpRequest(); xhr.open('POST', "2c-ajax-track.php", true); xhr.onload = function () { var res = JSON.parse(this.response); // OK // @TODO - UPDATE YOUR MAP PINS OR WHATEVER CONTROLS YOU WANT if (res.status==1) { map.innerHTML = ""; for (var rid in res.message) { var rider = res.message[rid]; // rider.track_lng // rider.track_lat // rider.track_time var dummy = document.createElement("div"); dummy.innerHTML = "Rider ID " + rid + " Lng " + rider.track_lng + " Lat " + rider.track_lat + " Updated " + rider.track_time; map.appendChild(dummy); } } // ERROR else { track.map.innerHTML = res.message; } }; xhr.send(data); } }; window.addEventListener("load", function(){ track.map = document.getElementById("map"); track.show(); setInterval(track.show, track.delay); }); </script> </head> <body> <div id="map"></div> </body> </html>
도대체 지도는 어디로 갔습니까? 글쎄, 구글 맵, 애플 맵, Here 맵 등 여러분 자신의 통합과 결정에 달려 있습니다.
유용한 비트
이것으로 코드가 완성되었으며 여기에 유용한 몇 가지 추가 기능이 있습니다.
한계 및 실시간 추적?
이봐, 이것은 실시간 시스템이 아니다! 물론 그렇지 않습니다. 그렇게 하는 것이 가능하지만 기술적 인 한계를 고려해야 하며 그만한 가치가 있습니다.
그러니… 누군가가 그런 종류의 돈을 기꺼이 내놓고 자신의 사업에 도움이 된다고 생각한다면…
링크 및 참조
등록된 댓글이 없습니다.