egeloen/google-map
PHP 5.6+ Google Maps JavaScript API v3 integration. Build and render maps with configurable controls, overlays, events and services via helpers, plus easy API script rendering with your key.
Installation:
composer require egeloen/google-map
Add the package to config/app.php under providers if using Laravel’s service container.
First Use Case: Render a basic map with a marker in a Laravel Blade view:
use Ivory\GoogleMap\Helper\Builder\MapHelperBuilder;
use Ivory\GoogleMap\Map;
use Ivory\GoogleMap\Overlay\Marker;
$map = new Map();
$marker = new Marker(new \Ivory\GoogleMap\Base\Coordinate(48.8584, 2.2945));
$map->getOverlayManager()->addMarker($marker);
$mapHelper = MapHelperBuilder::create()->build();
echo $mapHelper->render($map);
Key Files:
resources/views/maps/basic.blade.php: Placeholder for map rendering.config/services.php: Add Google Maps API key (if using helpers).Map Initialization:
$map = new Map();
$map->setCenter(new \Ivory\GoogleMap\Base\Coordinate(48.8584, 2.2945))
->setZoom(12);
Overlay Management:
$marker = new Marker($coordinate, ['title' => 'Paris']);
$map->getOverlayManager()->addMarker($marker);
$infoWindow = new InfoWindow('Paris, France');
$marker->setInfoWindow($infoWindow);
Event Handling:
$map->addEventListener('click', function($event) {
// Handle click event
});
Layer Integration:
$geoJsonLayer = new GeoJsonLayer('path/to/file.geojson');
$map->getLayerManager()->addGeoJsonLayer($geoJsonLayer);
Service Integration (e.g., Geocoding):
$geocoder = new \Ivory\GoogleMap\Service\Geocoder();
$geocoder->setAddress('Eiffel Tower, Paris');
$geocoder->setCallback(function($result) {
$map->setCenter($result->getLocation());
});
Service Container Binding:
$this->app->bind('google-map', function() {
return new Map();
});
Blade Directives: Create a custom directive for reusable map rendering:
Blade::directive('map', function($expression) {
return "<?php echo app('google-map')->render($expression); ?>";
});
Usage:
@map($map)
Configuration:
Store API key and defaults in config/google-map.php:
return [
'api_key' => env('GOOGLE_MAPS_API_KEY'),
'defaults' => [
'zoom' => 10,
'center' => [48.8584, 2.2945],
],
];
API Key Management:
Coordinate Precision:
floatval() for coordinates to avoid precision issues:
$coordinate = new \Ivory\GoogleMap\Base\Coordinate(floatval($lat), floatval($lng));
Event Listener Scope:
click or zoom_changed require the map to be fully rendered. Attach listeners after rendering:
$mapHelper->render($map);
$map->addEventListener('click', $callback);
Marker Clustering:
$map->getOverlayManager()->getMarkerCluster()->setType(MarkerClusterType::MARKER_CLUSTERER);
foreach ($markers as $marker) {
$map->getOverlayManager()->addMarker($marker);
}
Static Maps:
Console Logs:
Use JavaScript console.log in custom callbacks to debug events:
$map->addEventListener('click', function($event) {
$event->setCallback("console.log('Clicked at: ' + event.latLng.toUrlValue());");
});
Variable Naming Conflicts:
setVariable('custom_map')) don’t conflict with existing JavaScript variables.CORS Issues:
Custom Overlays:
Extend the OverlayInterface to create new overlay types:
class CustomOverlay implements OverlayInterface {
public function render(Map $map) { /* ... */ }
}
Helper Extensions:
Override MapHelper to add Laravel-specific features:
class LaravelMapHelper extends MapHelper {
public function renderWithAuth(Map $map) {
$this->setApiKey(config('google-map.api_key'));
return parent::render($map);
}
}
Service Decorators:
Decorate services (e.g., Geocoder) to add middleware:
class CachedGeocoder implements GeocoderInterface {
private $geocoder;
public function __construct(Geocoder $geocoder) {
$this->geocoder = $geocoder;
}
public function setAddress($address) {
// Add caching logic
$this->geocoder->setAddress($address);
}
}
Dynamic Styling:
Use the MapType class to apply custom map styles:
$mapType = new MapType();
$mapType->setOptions([
'styles' => [
{ 'featureType': 'poi', 'stylers': [ 'visibility': 'off' ] }
]
]);
$map->setMapType($mapType);
Lazy Loading: Load maps dynamically via AJAX to reduce initial page load time:
// In Blade
<div id="map-container"></div>
<script>
fetch('/load-map')
.then(response => response.text())
.then(html => {
document.getElementById('map-container').innerHTML = html;
});
</script>
Cluster Optimization:
For large datasets, use MarkerClusterer with gridSize:
$map->getOverlayManager()->getMarkerCluster()
->setOption('gridSize', 50);
Image Optimization:
How can I help you explore Laravel packages today?