Tutorials

Article Content:Codeigniter google maps geolocation integration

Codeigniter google maps geolocation integration

Codeigniter google maps geolocation integration.

Hi my friends, in the last week I have an awesome task I liked to share, the client asked me to build a reservation service form which using google map service to find the closest providers to client location by detecting his location and search in the database by latitude and longtuide ,it was in this scenario:

1- User opens the form, once he did, Geolocation API will detect his location, send latitude and longitude to Google map and set it to hidden inputs.

2- Then Google map displays his location with information window with the sentence (Your Location Is Here), after this draw a circle around your location with 30 kilometers.

3- Under Google map, there's a (show positions) button related to a RelatedLocationAjax() function by onclick() event, when the user clicks the button the Ajax function will be fired to call a closest_locations() function in the controller.

4- closest_locations () function will call get_closest_locations() function in the model which has a query to select all providers by ServiceId and about 30 kilometers distance around current latitude and longitude to the user.

5- closest_locations() will take all results as array and Output to JSON array.

6- In the view, you will take the ajax result from RelatedLocationAjax() function and pass to add_markers(result) function which responsible to push all providers to the map as markers with their information

7-After drawing all markers you will see the count of providers around your location displays above the map, as example (10 Providers Available), and the map will reset position again to fit to your location with all markers to sure that all markers displayed on the map.

What Will You Learn In This Tutorial?
-Find Your Location with Geolocation API 
-Integrate Geolocation with Google Map To Display Your Location On Google Map 
-Store get coordinates from google maps in database MySQL Nearest Locations to Your Location With Mysql 
-Display locations dynamically with google markers 
-Draw circle around all markers
-Use info window dynamically to display users information 
-Pick up latitude and longitude from markers and geolocation to input form or ajax request 
-Integrate all these features with codeigniter

This is the theory side, let’s do it practically my friends to describe it step by step as we always do.

1- Create Database Schema :

Import Services Table and Providers to Your database "demo"

--
-- Table structure for table `ci_providers`
--

CREATE TABLE `ci_providers` (
  `user_id` int(11) NOT NULL,
  `fullname` varchar(40) NOT NULL,
  `lat` float(10,6) NOT NULL,
  `lng` float(10,6) NOT NULL,
  `email` varchar(254) NOT NULL
) ENGINE=InnoDB DEFAULT CHARSET=utf8;

--
-- Dumping data for table `ci_providers`
--

INSERT INTO `ci_providers` (`user_id`, `fullname`, `lat`, `lng`, `email`) VALUES
(1, 'ahmed', 29.956051, 30.913300, [email protected]'),
(2, 'fakhr', 29.957001, 30.914499, [email protected]');

--
-- Table structure for table `ci_services`
--

CREATE TABLE `ci_services` (
  `ServiceId` int(11) NOT NULL,
  `user_id` int(11) NOT NULL,
  `ServiceName` varchar(50) DEFAULT NULL,
  `ServiceDesc` varchar(255) DEFAULT NULL,
  `CreatedAt` int(11) NOT NULL,
  `Order` int(11) NOT NULL,
  `Status` tinyint(1) NOT NULL
) ENGINE=MyISAM DEFAULT CHARSET=utf8 COMMENT='Services Table';

--
-- Dumping data for table `ci_services`
--

INSERT INTO `ci_services` (`ServiceId`, `user_id`, `ServiceName`, `ServiceDesc`, `CreatedAt`, `Order`, `Status`) VALUES
(1, 1, 'Service Name', 'Service Describtion', 1488098862, 1, 1),
(2, 2, 'Service Name', 'Service Describtion', 1488098862, 1, 1);

2- Create Services.php Controller with three functions 

book_service() function to load the book_service view and index to auto redirect when open the services controller

  // this function will redirect to book service page
    function index()
    {
        $this->book_service();
    }


 // this function to load service book page
    function book_service()
    {

        $this->view('content/book_service');

    }
closest_locations() function to receive ajax request and return closest providers as json output , we use foreach loop to change result by adding link in the info window (optionally)

    // this function receive ajax request and return closest providers
    function closest_locations(){

        $location =json_decode( preg_replace('/\\\"/',"\"",$_POST['data']));
        $lan=$location->longitude;
        $lat=$location->latitude;
        $ServiceId=$location->ServiceId;
        $base = base_url();
        $providers= $this->services_model->get_closest_locations($lan,$lat,$ServiceId);
        $indexed_providers = array_map('array_values', $providers);
        // this loop will change retrieved results to add links in the info window for the provider
        $x = 0;
        foreach($indexed_providers as $arrays => &$array){
            foreach($array as $key => &$value){
                if($key === 1){
                    $pieces = explode(",", $value);
                    $value = "$pieces[1]<a href='$base$pieces[0]'>More..</a>";
                }

                $x++;
            }
        }
        echo json_encode($indexed_providers,JSON_UNESCAPED_UNICODE);

    }

Data returned as json will be like this :

  var locations = [
     ["Ahmed Fakhr","Do this service 1 <a href=''>more</a>",  "29.957051,30.914529", "http://maps.google.com/mapfiles/ms/icons/blue.png"],
     ["Ali", "Do this service 1 <a href=''>more</a>", "29.956051,30.913529", "http://maps.google.com/mapfiles/ms/icons/green.png"],
     ["Mahmoud","Do this service 1 <a href=''>more</a>","29.955051,30.912529", "http://maps.google.com/mapfiles/ms/icons/red.png"],
     ];

3- Create Services_model.php Controller with one function

This function will select the only closeset providers in 30 kilometers distance  around current latitude and longitude by using Haversine Formula , and filter results by service type

class Services_model extends CI_Model
{

    // get closest providers
    // around 30 kilo meters from your location
    // by using latitude , longtuide and service id //
    function get_closest_locations($lng,$lat,$ServiceId){
        $results= $this->db->query("SELECT fullname,CONCAT(ci_providers.user_id,',',ServiceDesc) AS dscr,CONCAT(lat,',', lng) as pos,'http://maps.google.com/mapfiles/ms/icons/green.png' AS icon,
    ( 6371 * acos( cos( radians({$lat}) ) * cos( radians( `lat` ) ) * cos( radians( `lng` ) - radians({$lng}) ) + sin( radians({$lat}) ) * sin( radians( `lat` ) ) ) ) AS distance
    FROM ci_providers
    INNER JOIN ci_services  ON ci_services.user_id = ci_providers.user_id
    AND ci_services.ServiceId = $ServiceId
    HAVING distance <= 30
    ORDER BY distance ASC
      ")->result_array();
        return $results;
    }
}

4- Create book_service.php in views directory

First, add the form that collect servce id , available providers counter , display map, and fill the hidden inputs for current latitude and longtuide

 you will also notice  click event related to show closest providers button

                <form id="ServiceRequest" action="<?= current_url() ?>" method='post'>

                    <!-- dropdown service id  !-->
                    <div class="form-group">
                        <label class="control-label">ServiceType:</label>
                        <select name="Service_type" class="form-control" id="ServiceId">
                            <option>--all--</option>
                            <option value="1" selected>Service One</option>
                            <option value="2">Service Two</option>
                        </select>
                    </div>

                    <div class="form-group">
                        <!-- provider_counter service id  !-->
                        <label for="provider_counter" class="control-label">Closest Providers :</label>
                        <div class="text-lg-center alert-danger"id="info"></div>
                        <!-- display map  !-->
                        <div id="map" style="height: 600px; width:800px;"></div>
                        <!-- current latituide and longtuide  !-->
                        <input id="lat" type="hidden" value="" />
                        <input id="lng" type="hidden" value="" />
                        <button type="button" onclick="RelatedLocationAjax();">show_closest_providers</button>
                    </div>

                    <div id='submit_button'>
                        <input class="btn btn-success" type="submit" name="submit" value="add comment"/>
                    </div>
                </form>

The second part of this file is the most important part which do all the process in javascript to google map api 3 and with ajax requests, i describe all code with comments, so i recommended to read all comments to understand what we do here , i made i readable as much possible

<script>

    var lat = document.getElementById("lat"); // this will select the input with id = lat 
    var lng = document.getElementById("lng"); // this will select the input with id = lng   
    var info = document.getElementById("info"); // this will select the current div  with id = info 
    var ServiceId = document.getElementById("ServiceId"); // this will select the input with id = ServiceId 
    var locations = [];
    var km = 30; // this kilometers used to specify circle wide when use drawcircle function
    var Crcl ; // circle variable
    var map; // map variable
    var mapOptions = {
        zoom: 11,
        center: {lat:24.774265, lng:46.738586}
    }; // map options
    var markers = []; // markers array ,we will fill it dynamically
    var infoWindow = new google.maps.InfoWindow(); // information window ,we will use for our location and for markers
    // this will initiate when load the page and have all
    function initialize() {
        // set the map to the div with id = map and set the mapOptions as defualt
        map = new google.maps.Map(document.getElementById('map'),
            mapOptions);

        var infoWindow = new google.maps.InfoWindow({map: map});

        // get current location with HTML5 geolocation API.
        if (navigator.geolocation) {
            navigator.geolocation.getCurrentPosition(function(position) {
                var pos = {
                    lat: position.coords.latitude,
                    lng: position.coords.longitude
                };
                lat.value  =  position.coords.latitude ;
                lng.value  =  position.coords.longitude;
                info.nodeValue =  position.coords.longitude;
                // set the current posation to the map and create info window with (Here Is Your Location) sentense
                infoWindow.setPosition(pos);
                infoWindow.setContent('Here Is Your Location.');
                // set this info window in the center of the map 
                map.setCenter(pos);
                // draw circle on the map with parameters
                DrowCircle(mapOptions, map, pos, km);

            }, function() {
                // if user block the geolocatoon API and denied detect his location
                handleLocationError(true, infoWindow, map.getCenter());
            });
        } else {
            // Browser doesn't support Geolocation
            handleLocationError(false, infoWindow, map.getCenter());

        }
    }
    // to handle user denied
    function handleLocationError(browserHasGeolocation, infoWindow, pos) {
        infoWindow.setPosition(pos);
        infoWindow.setContent(browserHasGeolocation ?
            'Error: User Has Denied Location Detection.' :
            'Error: Your browser doesn\'t support geolocation.');
    }

    // to draw circle around 30 kilometers to current location
    function DrowCircle(mapOptions, map, pos, km ) {
        var populationOptions = {
            strokeColor: '#FF0000',
            strokeOpacity: 0.8,
            strokeWeight: 2,
            fillColor: '#FF0000',
            fillOpacity: 0.35,
            map: map,
            center: pos,
            radius: Math.sqrt(km*500) * 100
        };
        // Add the circle for this city to the map.
        this.Crcl = new google.maps.Circle(populationOptions);
    }
    // this function to get providers with ajax request
    function RelatedLocationAjax() {
        $.ajax({
            type: "POST",
            url: "<?= base_url() ?>services/closest_locations",
            dataType: "json",
            data:"data="+ '{ "latitude":"'+ lat.value+'", "longitude": "'+lng.value+'", "ServiceId": "'+ServiceId.value+'" }',
            success:function(data) {
                // when request is successed add markers with results
                add_markers(data);
            }
        });
    }
    // this function to will draw markers with data returned from the ajax request
    function add_markers(data){
        var marker, i;
        var bounds = new google.maps.LatLngBounds();
        var infowindow = new google.maps.InfoWindow();
        // display how many closest providers avialable 
        document.getElementById('info').innerHTML = " Available:" + data.length + " Providers<br>";

        for (i = 0; i < data.length; i++) {
            var coordStr = data[i][2];
            var coords = coordStr.split(",");
            var pt = new google.maps.LatLng(parseFloat(coords[0]), parseFloat(coords[1]));
            bounds.extend(pt);
            marker = new google.maps.Marker({
                position: pt,
                map: map,
                icon: data[i][3],
                address: data[i][1],
                title: data[i][0],
                html: data[i][0] + "<br>" + data[i][1]
            });
            markers.push(marker);
            google.maps.event.addListener(marker, 'click', (function (marker, i) {
                return function () {
                    infowindow.setContent(marker.html);
                    infowindow.open(map, marker);
                }
            })
            (marker, i));

        }
        // this is important part , because we tell the map to put all markers inside the circle,
        // so all results will display and centered
        map.fitBounds(this.Crcl.getBounds());
    }

    google.maps.event.addDomListener(window, 'load', initialize);

</script>
<script async defer
        src="https://maps.googleapis.com/maps/api/js?key=AIzaSyDNyLsAhFt4hIZKeNJYC244jPPayM0GhrY&callback=initialize">
</script>

The Finall result will be Like his

Download Link



  • Mamta
    Can you please upload a live demo also on this page so that we could run the code and see the result for once before start learning from this tutorial?
    April 7, 2017
    Reply
    • admin
      [email protected]
      sorry , but this is not available for this tutorial,you can download full example and follow every step in the video and the code will run thanks
      April 9, 2017
      Reply
  • yongyt
    verry good
    April 25, 2017
    Reply
    • admin
      [email protected]
      You Are Welcome , yongyt
      April 26, 2017
      Reply
  • Gema
    its very nice, but i want to enquire, when i click show closest provider, it dont want to show up, please sir can you help me about this
    May 3, 2017
    Reply
    • admin
      [email protected]
      Yes, this is true because you should update the table by nearest latitudes and longitudes to your current location; I tested it in the video after adding some nearest latitudes and longitudes to my current location, so to fix this 1- Get your current latitude and longitude 2- Add some nearest latitudes and longitudes in the table 3- Test again, and it will works
      May 4, 2017
      Reply
  • ayush
    HI...i imported all the tables in my demo database as well as extracted the zip file from the downloading link.But in the extracted link thsre is no folder of codeigniter-nearest-markers-map.Thus when i type URL llocalhost/codeigniter-nearest-markers-map/# error is coming...please send me the remaining file..
    July 22, 2017
    Reply

Leave a Reply

Your email address will not be published.


Notify me of followup comments via e-mail.
You can also Subscribe without commenting.