Add Events to a Mapbox map via PHP
Adding a map to your application is very easy to do these days. You might use the more popular google maps, but Mapbox makes this process really simple. In order to create a map, you will use Javascript, but to save and provide data for the map we will use php.
Video Guide:
Source Code:
Helpful Links:
Written Guide:
Basic Pages, and styles
Basic HTML
<div class="flex font-sans">
<!-- SIDEBAR -->
<div class="w-1/5 bg-gray-900 h-screen">
<!-- LOGO -->
<div class="flex justify-center pt-8 pb-8 border-b border-b-white">
<img src="../dist/mapbox-logo-white.svg" class="h-14" />
</div>
<!-- HEADING -->
<h3 class="text-white font-bold text-center text-3xl mt-8 flex items-center w-full justify-center">
<svg xmlns="http://www.w3.org/2000/svg" class="h-10 w-10 mr-1" fill="none" viewBox="0 0 24 24" stroke="currentColor"
stroke-width="2">
<path stroke-linecap="round" stroke-linejoin="round" d="M12 6v6m0 0v6m0-6h6m-6 0H6" />
</svg>
Add an Event
</h3>
<!-- ADD EVENT FORM -->
<div class="mb-6 w-5/6 mx-auto mt-12">
<label for="eventName" class="block mb-2 text-sm font-medium text-gray-900 dark:text-gray-300">Event Name</label>
<input type="text" id="eventName" class="input-field" placeholder="DC Event" required>
</div>
<div class="mb-6 w-5/6 mx-auto mt-6">
<label for="eventDescription" class="block mb-2 text-sm font-medium text-gray-900 dark:text-gray-300">Event
Description</label>
<input type="text" id="eventDescription" class="input-field" placeholder="There will be very cool refreshments"
required>
</div>
<div class="mb-6 w-5/6 mx-auto mt-6">
<label for="geocoder" class="block mb-2 text-sm font-medium text-gray-900 dark:text-gray-300">Event Address</label>
<div id="geocoder"></div>
</div>
<div class="w-5/6 mx-auto flex justify-end">
<button type="button" class="submit-button" onclick="addEvent()">Add Event</button>
</div>
</div>
<!-- MAP -->
<div class="h-screen w-full" id="map"></div>
</div>
Styles
Header Dependencies
<link rel="preconnect" href="https://fonts.googleapis.com">
<link rel="preconnect" href="https://fonts.gstatic.com" crossorigin>
<link href="https://fonts.googleapis.com/css2?family=Inter:wght@400;500;600;700;800;900&family=Poppins:wght@400;500;600;700;900&display=swap" rel="stylesheet">
<link rel="stylesheet" href="https://api.mapbox.com/mapbox-gl-js/plugins/mapbox-gl-geocoder/v5.0.0/mapbox-gl-geocoder.css" type="text/css">
<link href="../dist/output.css" rel="stylesheet">
Mapbox, JQuery Dependencies
<script src="https://code.jquery.com/jquery-3.6.0.min.js" integrity="sha256-/xUj+3OJU5yExlq6GSYGSHk7tPXikynS7ogEvDej/m4=" crossorigin="anonymous"></script>
<script src='https://api.mapbox.com/mapbox-gl-js/v2.9.1/mapbox-gl.js'></script>
<link href='https://api.mapbox.com/mapbox-gl-js/v2.9.1/mapbox-gl.css' rel='stylesheet' />
<script src="https://api.mapbox.com/mapbox-gl-js/plugins/mapbox-gl-geocoder/v5.0.0/mapbox-gl-geocoder.min.js"></script>
Initialize Your Map (In a script tag)
mapboxgl.accessToken = 'YOUR_MAPBOX_TOKEN_HERE';
var map = new mapboxgl.Map({
container: 'map',
style: 'mapbox://styles/mapbox/streets-v11',
center: [-77.04, 38.907],
zoom: 11.15
});
Get Events Data & Add to Map
Load an icons layer onto your map
map.on('load', function () {
//place object we will add our events to
map.addSource('places',{
'type': 'geojson',
'data': {
'type': 'FeatureCollection',
'features': []
}
});
//add place object to map
map.addLayer({
'id': 'places',
'type': 'symbol',
'source': 'places',
'layout': {
'icon-image': '{icon}',
'icon-allow-overlap': true
}
});
//Handle popups
map.on('click', 'places', (e) => {
const coordinates = e.features[0].geometry.coordinates.slice();
const description = e.features[0].properties.description;
while (Math.abs(e.lngLat.lng - coordinates[0]) > 180) {
coordinates[0] += e.lngLat.lng > coordinates[0] ? 360 : -360;
}
new mapboxgl.Popup()
.setLngLat(coordinates)
.setHTML(description)
.addTo(map);
});
//Handle pointer styles
map.on('mouseenter', 'places', () => {
map.getCanvas().style.cursor = 'pointer';
});
map.on('mouseleave', 'places', () => {
map.getCanvas().style.cursor = '';
});
//get our data from php function
//getAllEvents();
});
Async get events data from PHP
function getAllEvents(){
$.ajax({
url: "../api/getAllEvents.php",
contentType: "application/json",
dataType: "json",
success: function (eventData) {
console.log(eventData)
map.getSource('places').setData({
'type': 'FeatureCollection',
'features': eventData
});
},
error: function (e) {
console.log(e);
}
});
}
Create a new database
Add an events table
Create your id, event, lat, lng columns, name, and description
Your table should look like this:
Connect your PHP file that handles events to your DB
<?php
$db = "mapboxevents";
$host = "localhost";
$user = 'USERNAME';
$pass = 'PASSWORD';
//PDO Connection
try {
$pdo = new PDO("mysql:host=$host;dbname=$db", $user, $pass);
$pdo->setAttribute(PDO::ATTR_ERRMODE, PDO::ERRMODE_EXCEPTION);
//echo "Connected successfully";
}
catch(PDOException $e){
//echo "Connection failed: " . $e->getMessage();
}
function p($arr){
echo "<pre>";
print_r($arr);
echo "</pre>";
}
Get event data from your events table
$sql = "SELECT * FROM events";
try {
$stmt = $pdo->prepare($sql);
$stmt->execute();
$data = $stmt->fetchAll(PDO::FETCH_ASSOC);
} catch (Exception $e) {
die($e);
}
Morph your $data from mySQL Into json Mapbox can use
foreach ($data as $key => $eventData) {
$returnData[] = [
'type' => 'Feature'.$eventData['id'],
'properties' => [
'description' => '<strong>'.$eventData['name'].'</strong><p>'.$eventData['description'].'</p>',
'icon' => 'rocket-15'
],
'geometry' => [
'type' => 'Point',
'coordinates' => [$eventData['lat'], $eventData['lng']]
]
];
}
Set your headers to support json, and echo out your json
//top of file
header('Content-Type: application/json; charset=utf-8');
include('db.php');
//bottom of file
echo json_encode($returnData);
Test your first event, by adding it into your mySQL
INSERT INTO `events` (`id`, `name`, `description`, `lat`, `lng`) VALUES (NULL, 'Manual mySQL', 'Test mySQL event', '-77.0877945', '38.937867');
Add events to your database:
Your php file will contain a simple PDO sql statement that will insert all of the posted variables, including name, description, lat, and lng
PHP Process File that will add to DB
<?php
// api/createEvent.php
include('db.php');
if(isset($_POST['name'])){
$sql = "INSERT into events (name,description,lat,lng) VALUES (:name,:description,:lat,:lng)";
try {
$stmt = $pdo->prepare($sql);
$stmt->execute([
'name'=>$_POST['name'],
'description'=>$_POST['description'],
'lat'=>$_POST['lat'],
'lng'=>$_POST['lng'],
]);
echo json_encode('success');
} catch (Exception $e) {
die($e);
}
}
Async JavaScript file to call your API file
function addEvent(){
$.ajax({
url: "../api/createEvent.php",
type:'POST',
data:postObj,
dataType: "json",
success: function (resp) {
},
error: function (e) {
console.log(e);
}
});
}
Initialize Your Geocoder to get lat, lng data
const geocoder = new MapboxGeocoder({
accessToken: mapboxgl.accessToken,
});
geocoder.addTo('#geocoder');
var geocoderResult = {};
geocoder.on('result', (e) => {
geocoderResult = e.result, null, 2;
});
// Clear results container when search is cleared.
geocoder.on('clear', () => {
geocoderResult = {};
});
Validate if geocoder is set & set postData
if(geocoderResult=={}){
return false;
}
var postObj = {
name:$("#eventName").val(),
description:$("#eventDescription").val(),
lat:geocoderResult.center[0],
lng:geocoderResult.center[1],
}
Handle success when event is created
//reset form & get new data
$("#eventName").val('');
$("#eventDescription").val('');
geocoder.clear();
getAllEvents();