Jun 05 2010

Google map v3 Cakephp Helper

Category: CakePHP,Google,Google Maps,PHP,Web toolspaomic @ 9:06 am

Recetly I found out a nice google maps helper for Cakephp, but it is based on version 2. There is a new versione of the API, v3, which has many improvements,  including faster loading time, better compatibility with mobile devices and more. Since I could not find an helper for this new version, I decided to create it on my own, and here is it!!

First, create the googlemap.php file under views / helpers, and copy/paste this:

<?php
/*
 * CakeMap -- a google maps integrated application built on CakePHP framework.
 * Based on initial versione from Garrett J. Woodworth : gwoo@rd11.com
 * Rewritten by  : http://www.small-software-utilities.com
 *
 * @author      info@small-software-utilities.com
 * @version     0.2
 * @license     OPPL
 *
 * Modified by     Mahmoud Lababidi <lababidi@bearsontherun.com>
 * Date        Dec 16, 2006
 * Rewritten by small software utilities <info@small-software-utilities.com>
 * Date        May, 2010
 */
class GoogleMapHelper extends Helper {
    var $errors = array();
    var $key = "your key here, not needed for v3";
    var $url ="http://maps.google.com/maps/api/js?sensor=false";
    function map($default, $style = 'width: 400px; height: 400px' )
    {
        //if (empty($default)){return "error: You have not specified an address to map"; exit();}
        $out = "<div id=\"map\"";
        $out .= isset($style) ? "style=\"".$style."\"" : null;
        $out .= " ></div>";
        $out .= "
        <script type=\"text/javascript\">
        //<![CDATA[
     var directionDisplay;
    var directionsService = new google.maps.DirectionsService();
    var map;
    var iconimage = \"http://labs.google.com/ridefinder/images/mm_20_red.png\";
         var iconshadow = \"http://labs.google.com/ridefinder/images/mm_20_shadow.png\";
         var myOptions = {
            zoom: ".$default['zoom'].",
            center: new google.maps.LatLng(".$default['lat'].", ".$default['long']."),
            mapTypeId: google.maps.MapTypeId.ROADMAP,
        streetViewControl: true
          };
      var map = new google.maps.Map(document.getElementById(\"map\"), myOptions);
      // global infowindow object
      var globalInfowindow = new google.maps.InfoWindow();
      function cleardirs()
      {
          if(directionsDisplay)
              directionsDisplay.setMap(null);
          div = document.getElementById('".(isset($default['directions_div'])?$default['directions_div']:'directions_div')."');
          if(div)
              div.innerHTML = \"\";
      }
               ";
    if(isset($default['directions_div']))
            {
                $out .= "
                  directionsDisplay = new google.maps.DirectionsRenderer();
              directionsDisplay.setMap(map);
              directionsDisplay.setPanel(document.getElementById('".$default['directions_div']."'));
              function calcRoute(fromid,tolat,tolon) {
              directionsDisplay.setMap(map);
                from = document.getElementById(fromid).value;
              var start = from;
              var end = new google.maps.LatLng(tolat,tolon);
              var request = {
                origin:start,
                destination:end,
                travelMode: google.maps.DirectionsTravelMode.DRIVING
              };
              directionsService.route(request, function(result, status) {
                if (status == google.maps.DirectionsStatus.OK) {
                  directionsDisplay.setDirections(result);
                }
              });
}
                ";
            }
        $out .="
        //]]>
        </script>";
        return $out;
    }
    function addMarkers(&$data, $icon=null)
    {
        $out = "
            <script type=\"text/javascript\">
            //<![CDATA[
            ";
            if(is_array($data))
            {
                $i = 0;
                foreach($data as $n=>$m){
                    $keys = array_keys($m);
                    $point = $m[$keys[0]];
                    if(!preg_match('/[^0-9\\.\\-]+/',$point['longitude']) &&
preg_match('/^[-]?(?:180|(?:1[0-7]\\d)|(?:\\d?\\d))[.]{1,1}[0-9]{0,15}/',$point['longitude'])
                        && !preg_match('/[^0-9\\.\\-]+/',$point['latitude']) &&
preg_match('/^[-]?(?:180|(?:1[0-7]\\d)|(?:\\d?\\d))[.]{1,1}[0-9]{0,15}/',$point['latitude']))
                    {
                        $out .= "
                            var point".$i." = new google.maps.LatLng(".$point['latitude'].",".$point['longitude'].");
                            var marker".$i." = new google.maps.Marker({
                                  position: point".$i.",
                      map: map,
                      title:\"".(isset($point['title'])?$point['title']:'')."\",
                      shadow: iconshadow,
                    icon: iconimage,
                            });";
                        if(isset($point['title'])&&isset($point['html']))
                        {
                           $out .= " var infowindow$i = new google.maps.InfoWindow({
                          content: \"$point[title]$point[html]\"
                      });
                      google.maps.event.addListener(marker".$i.", 'click', function() {
                  infowindow$i.open(map,marker".$i.");
                });";
                        }
                        $data[$n][$keys[0]]['js']="marker$i.openInfoWindowHtml(marker$i.html);";
                        $i++;
                    }
                }
            }
        $out .=    "
                //]]>
            </script>";
        return $out;
    }
    function addClick($var, $script=null)
    {
        $out = "
            <script type=\"text/javascript\">
            //<![CDATA[
            $script
            google.maps.event.addListener(map, 'click', ".$var.", true);
            //]]>
            </script>";
        return $out;
    }
    function addMarkerOnClick($innerHtml = null)
    {
        $mapClick = '
            var mapClick = function (event) {
                var marker = new google.maps.Marker({
                position:event.latLng,
                icon: iconimage,
                map:map
                });
                var infowindow = new google.maps.InfoWindow({
            content: \"'.$innerHtml.'\"
        });
        google.maps.event.addListener(marker, \'click\', function() {
              infowindow.open(map,marker);
        });
            }
        ';
        return $this->addClick('mapClick', $mapClick);
    }
    function moveMarkerOnClick($lngctl, $latctl, $innerHtml = null)
    {
        $mapClick = '
            var mapClick = function (event) {
                marker0.setPosition(event.latLng);
                lngctl = document.getElementById(\''.$lngctl.'\');
                latctl = document.getElementById(\''.$latctl.'\');
                if(lngctl)
                 lngctl.value = event.latLng.lng();
                if(latctl)
                 latctl.value = event.latLng.lat();
            }
        ';
        return $this->addClick('mapClick', $mapClick);
    }
}
?>

To use you just need to add the helper to the controller, or to AppController if you want this in every other controller, like this:

<?php
class MyController extends AppController {
    var $helpers = array( 'Googlemap');
....
}

Then, in the view, add these line:

        $default = array('type'=>'0','zoom'=>13,'lat'=>'42.5846353751749',
'long'=>'11.5191650390625');
        $points = array();
        $points[0]['Point'] = array('longitude' =>$default['long'],'latitude' =>$default['lat']);
        $key = $googlemap->key;
        echo $javascript->link($googlemap->url);
        echo $googlemap->map($default,'width: 600px; height: 400px');
        echo $googlemap->addMarkers($points);
        echo $googlemap->moveMarkerOnClick('StructureLongitudine','StructureLatitudine');

A simple explanation:

points is the array where your store, guess, points! The map methos writes out the js for the map, the addMarkers method add markers to the page. The last method, moveMarkerOnClick, was useful to me, for user placement. With this code you can create a map where the user can click to move the marker. Note that the marker which moves is always the one called marker0. The two methos parameters are the ids of two input boxes, representing latitude and longitude. This id is created automatically by CakePHP by using the usual syntax ControllernameInputname.  The default variable contains map type, zoom level, center of the map respectively. You can also add directions to your map by adding a div, setting and id for it and then passing the id in the default array like this:

'directions_div'=>'directions_div'

You can also use the addMarkerOnClick function, which adds a marker when you click on the map. InfoWindows are supported, just add a title and html item to the point array, they will be used to create an infowindow to be displayed when you click on the marker icon.

Hope this helps!

PS: please not that this is a initial version of the helper, use it at your own risk! But please leave here some comments, feature request, bug, or else!

Thanks!

EDIT: According to Amjith, to use this in cakephp v1.3 you must use:

$this->GoogleMap-> instead of $googlemap->

and name the file helper as google_map.php

EDIT 2: According to Duckula, for compatibility with Cake 1.3, you should use:

var $helpers = array( ‘GoogleMap’);

with capital M.

Sorry for these, but I still did not have the chance to try out v1.3, but I will soon!

Share and Enjoy:
  • Digg
  • del.icio.us
  • Netvouz
  • DZone
  • ThisNext
  • MisterWong
  • Wists
  • blinkbits
  • BlinkList
  • blogmarks
  • BlogMemes
  • blogtercimlap
  • Blue Dot
  • Book.mark.hu
  • Bumpzee
  • co.mments
  • De.lirio.us
  • Fark
  • feedmelinks
  • Fleck
  • Furl
  • Gwar
  • kick.ie
  • Linkter
  • Ma.gnolia
  • MyShare
  • Netscape
  • NewsVine
  • Scoopeo
  • Simpy
  • Slashdot
  • Smarking
  • Spurl
  • StumbleUpon
  • Taggly
  • Technorati
  • Webride
  • YahooMyWeb
Post Tagged:

39 Responses to “Google map v3 Cakephp Helper”

  1. sajid says:

    thanks for this helper.
    there is type on line 152
    double “new new”

    feature request : sidebar with maps markers points

  2. paomic says:

    Thanks, corrected the bug. Regarding the feature request, do you mean a list of all markers on the map next or below the map itself? Must they be clickable or something?

  3. Mark says:

    Thanks for the helper – I’m setting it up now.

    I cannot help but wonder why you don’t include the code in a format that is easier to copy and paste. I appreciate your effort, but manually removing the line numbers from 187 lines of code is not fun.

  4. paomic says:

    You’re right, hope it’s better now!

  5. Mark says:

    Wow – that was really quick! I hadn’t even gotten around to editing 10 lines, and you had the fixed. Thanks so much!

  6. Amjith PS says:

    for new version of cakePHP 1.3 use in view

    $this->GoogleMap-> insterd of $googlemap->

    and name file helper as google_map.php

    Works great! keep rocking.

  7. Google Map for CakePHP 1.3 + says:

    [...] is another link i found for google map. Google Map Helper . You can copy this code for good map for your [...]

  8. paomic says:

    Thanks, I’ll add this.

  9. Sajid says:

    sorry for late reply about your questions regards my feature request for Sidebar

    yes you got what i meant.

    clicking on link in sidebar will highlight respective marker and vice-versa.

    i hope its clear to you now.

    thanks again

  10. Duckula says:

    in Cake 1.3 the helper-inclusion in the controller should be “var $helpers = array( ‘GoogleMap’);” (with a capital M)

  11. paomic says:

    Thanks, I edited the post with the explanation at the end! I hope to be able to try out cakephp v1.3 soon!

  12. zembar says:

    How can I add a function to close the opened info window when a new point is being clicked?

  13. igniteflow says:

    Thanks, this is great! As you mentioned in CakePHP change all occurrences of

    $googlemap-> to $this->GoogleMap

    var $helpers = array(‘GoogleMap’);

    and the helper file should be called ‘google_map.php’

  14. didik says:

    hii…sorry I’m newbie here…
    I have followed lababidi tutorial at http://bakery.cakephp.org/articles/view/adding-a-google-map-to-your-app and http://bakery.cakephp.org/articles/view/googlemaphelper

    and also change :
    $googlemap-> to $this->GoogleMap
    var $helpers = array(‘GoogleMap’);
    and the helper file should be called ‘google_map.php’

    but I cant try on my localhost, still error…
    may you give me success example of this tutorial?
    I’m confused, my googlemap never work..
    send me an email at deem_014@yahoo.com
    thank you so much.. :)

    regards,
    Didik

  15. paomic says:

    Hi, what kind of error do you get?

  16. didik says:

    there is no view in my index.ctp..

    I also have app\views\layouts\map.ctp :
    link($url);
    ?>

  17. didik says:

    sorry bad connection.. :)
    there is no view in my index.ctp..

    I also have app\views\layouts\map.ctp :
    link($url);
    ?>

  18. didik says:

    there is no view in my index.ctp..

    I also have app\views\layouts\map.ctp :
    link($url);
    ?>

    not bad connection but my code can’t read here.. :)
    so i use #…
    thank you paomic..

  19. paomic says:

    I don’t really understand your comment, did you try to add the lines that are written above in your view?

    $default = array(‘type’=>’0′,’zoom’=>13,’lat’=>’42.5846353751749′,
    ‘long’=>’11.5191650390625′);
    $points = array();
    $points[0]['Point'] = array(‘longitude’ =>$default['long'],’latitude’ =>$default['lat']);
    $key = $googlemap->key;
    echo $javascript->link($googlemap->url);
    echo $googlemap->map($default,’width: 600px; height: 400px’);

    echo $googlemap->addMarkers($points);

    echo $googlemap->moveMarkerOnClick(‘StructureLongitudine’,'StructureLatitudine’);

  20. paomic says:

    Try to remove the php tags (< ?) from your comment!

  21. didik says:

    still error with your view..

    this is my map.ctp:
    link($url);
    ? >

  22. didik says:

    map.ctp

    $key = “PASTE KEY HERE”;
    $url = “http://maps.google.com/maps?file=api&v=2&key=$key”;
    echo $javascript->link($url);

  23. paomic says:

    Where did you find this? This is not the helper described above! Besides, it’s also api version 2. Did you sign up for a key at http://code.google.com/apis/maps/signup.html and replaced “PASTE KEY HERE”?

  24. didik says:

    sorry before..hehe
    but now I use your tutorial, I copypaste all..
    so what can I do?
    in your tutorial, you only have 3 files right?
    1.views\helpers\google_map.php
    2.mycontroller
    3.index.ctp
    is that enough to make it work?
    I’m still confused…
    may I send my file to you?

    thank

  25. paomic says:

    I don’t think you copied those files, because at the top of the helper file there is:

    var $key = “your key here, not needed for v3″;
    var $url =”http://maps.google.com/maps/api/js?sensor=false”;

    which is not the same as in your previous comment (I copied and pasted the above text from this post!). Please check that again, copy the text exactly as you find it in the post (remember to rename correctly if you are using cake 1.3) and then, if you still have problems, we can try to solve them.

  26. didik says:

    I can see the map now even few of the function doesn’t work…
    thank you so much paomic….this is work!!!
    GREAT TUTORIAL…. :) :thumbup

  27. paomic says:

    Thanks! Which functions do not work?

  28. didik says:

    oh sorry paomic..
    there some mistake with my mind.. :D
    after I read all, they are working fine…
    I will tell my friend about your awesome website..

  29. rocky says:

    hii..are there tutorial how to add marker & save in database?
    thanks

  30. paomic says:

    Hi, did you create a model with the appropriate fields? In this example you just need to create a form with two fields, longitude and latitude. Then tou use this
    echo $googlemap->moveMarkerOnClick(‘StructureLongitudine’,'StructureLatitudine’);
    in this case Structure is the name of the model, so StructureLongitudine is the id of the input box generated by

    echo $form->create(‘Structure’);
    ..
    echo $form->input(‘latitude’);

  31. rocky says:

    yes of course..i have Place model with longitude and latitude fields…
    the form has been created but still I can’t save to the database…

  32. paomic says:

    Did you change this line:

    $googlemap->moveMarkerOnClick(‘StructureLongitudine’,’StructureLatitudine’);

    to

    $googlemap->moveMarkerOnClick(‘PlaceLongitudine’,’PlaceLatitudine’);

  33. rocky says:

    yes I did..
    but still not working..
    this is my controller :
    function add(){
    if(!empty($this->data)){
    $this->Place->create();
    if($this->Place->save($this->data)){
    $places = $this->Place->find(‘all’);
    $this->set(compact(‘$places’));
    $this->render(‘success’,'ajax’);
    }
    else{
    $this->render(‘failure’,'ajax’);
    }

    }
    }

    —————————–
    and my index.ctp

    <div id="map">
    <?php
    $default = array(‘type’=>’0′,’zoom’=>13,’lat’=>’-7.8′,
    ‘long’=>’110.3666667′);
    $places = array();
    $places[0]['Place'] = array(‘longitude’ =>$default['long'],’latitude’ =>$default['lat']);
    $key = $this->GoogleMap->key;
    echo $javascript->link($this->GoogleMap->url);
    echo $this->GoogleMap->map($default,’width: 600px; height: 400px’);
    echo $this->GoogleMap->addMarkers($places);
    echo $this->GoogleMap->moveMarkerOnClick(‘PlaceLongitudine’,'PlaceLatitudine’);
    ?>
    </div>
    <?php
    echo $form->create(‘Place’);
    echo $form->input(‘latitude’);
    echo $form->input(‘longitude’);
    echo $ajax->submit(‘add’,array(‘url’=>’/place/add’,'update’=>’places’));
    ?>

  34. rocky says:

    I use this to encode the php code http://centricle.com/tools/html-entities/
    thanks :)

  35. Rock says:

    Hi,
    Im facing problem in google map integration with cakephp. Please help me on this.

    Thanks

  36. Rock says:

    i m getting bellow error

    APP/views/points/index.ctp, line 53

    and i m not able to add and edit

  37. paomic says:

    Hi, you should be more precise, what kind of problem are you facing?

  38. Marco says:

    I folks, I need help to use direction option, I’m able to add markers but, I want to get route between them.Tks

  39. Naresh says:

    If i click on Marker how to get popup in this situation

Leave a Reply