Weave Code
Weaver
Helps Laravel developers discover, compare, and choose open-source packages. See popularity, security, maintainers, and scores at a glance to make better decisions.
Feedback
Share your thoughts, report bugs, or suggest improvements.
Subject
Message

Google Map Bundle Laravel Package

lendable/google-map-bundle

A Symfony bundle that integrates Google Maps into your application, providing services and Twig helpers to render maps, configure markers, and manage API settings from a central configuration.

View on GitHub
Deep Wiki
Context7

Getting Started

Read this first: it is not a Laravel package. lendable/google-map-bundle is a Symfony2 bundle (a fork of egeloen/ivory-google-map-bundle), it is archived since 2016, has zero dependents, and ships no service provider, facade, or package discovery. composer require lendable/google-map-bundle in a Laravel app gets you a bundle class that Laravel will never boot, plus a hard dependency on Symfony DI/Twig wiring you don't have.

That said, the value of the package is the underlying framework-agnostic library in the Ivory lineage (Ivory\GoogleMap\Map, Coordinate, Marker, InfoWindow, Ivory\GoogleMap\Helper\MapHelper). That part is plain PHP and can be driven from a Laravel controller. Treat the "bundle" as a documentation reference, not an install target.

Minimal path if you insist on using the library:

  1. Check PHP compatibility before anything else. Open composer.json in the repo and look at the php constraint. This code is PHP 5.5/7.x-era; expect friction (or hard failures) on PHP 8.1+. If the Lendable fork doesn't declare ^8.0, stop here.
  2. composer require lendable/google-map-bundle (or pull the underlying map library directly if the fork's autoload map is bundle-shaped).
  3. Put the key in config/services.php:
    'google_maps' => ['key' => env('GOOGLE_MAPS_KEY')],
    
  4. Bind a helper builder once in AppServiceProvider::register():
    $this->app->singleton(MapHelper::class, fn () => MapHelperBuilder::create()->build());
    
  5. In a controller, build the map and hand it to the view; in Blade, {!! $mapHtml !!} (unescaped is mandatory — the helper returns markup + <script>).

First use case: a single-location "find us" page — one Map, one Coordinate, one Marker, one InfoWindow. That exercises 90% of the API surface you'll ever need and tells you within an hour whether the library runs on your PHP version.

If the answer to step 1 is "no," skip to Gotchas — you're better off with a Blade component wrapping the Maps JS API.

Implementation Patterns

Render in the controller, not the view. The helper produces a container <div>, a map_js config object, and initialization code. Build it once and cache the string; it's deterministic for a given set of coordinates, so Cache::remember("map:{$id}", 3600, fn () => $helper->render($map)) works well for static store-locator pages.

Separate HTML from JS when you need control over script placement. Rather than render(), use the helper's HTML and JavaScript renderers individually so the JS can go in a @push('scripts') stack below the Google loader:

// Controller
return view('contact', [
    'mapHtml' => $helper->renderHtml($map),
    'mapJs'   => $helper->renderJavascript($map),
]);
{{-- contact.blade.php --}}
{!! $mapHtml !!}

@push('scripts')
<script src="https://maps.googleapis.com/maps/api/js?key={{ config('services.google_maps.key') }}"></script>
{!! $mapJs !!}
@endpush

This ordering matters: the generated JS calls new google.maps.Map(...) and will throw google is not defined if the API script hasn't loaded.

Wrap it in a Blade component for reuse. A <x-google-map :markers="$locations" /> component (class-based, taking an array of ['lat','lng','title','html']) keeps Ivory\GoogleMap\* imports out of your views and out of every controller. Inside the component, loop the array and add a Marker per entry, attaching an InfoWindow to each.

Overlay building is imperative and order-sensitive. The pattern is always: create Coordinate → create Marker with that coordinate → $map->getOverlayManager()->addMarker($marker) → create InfoWindow with content and coordinate → $marker->setInfoWindow($infoWindow) → $map->getOverlayManager()->addInfoWindow($infoWindow). Attach the InfoWindow to both the marker and the map, or clicking does nothing. Same shape for Polyline, Polygon, and Circle via the overlay manager.

Custom JS goes through the library, not around it. Instead of hand-writing event handlers and hoping the map variable is in scope, push Ivory\GoogleMap\Utility\.../Javascript objects onto the map so they're emitted inside the same initialization callback and can reference the generated map variable. This is the one place the library genuinely saves you work versus raw JS.

Multiple maps per page: give each Map a distinct htmlVariable/container id before rendering. The default id is shared and two render() calls in one response will collide on the DOM id and on the JS variable name.

Config: the bundle's Symfony config tree (ivory_google_map.api_key) does not exist in Laravel. Every "set the API key in config.yml" instruction in the README is dead weight — the library doesn't read it; the generated JS just points at the API script. You're responsible for injecting ?key= yourself.

Gotchas and Tips

  • The Symfony integration layer is unusable here. No DI extension, no Twig ivory_google_map() function, no bundle config, no app/config/config.yml. Any tutorial you find for Ivory Google Map Bundle will show Twig and YAML you cannot use. Translate to PHP + Blade, or ignore it.
  • Archived + zero stars + zero dependents = zero support surface. No security patches, no PHP 8 fixes, no Maps API updates. Budget for vendoring it or forking it if you adopt it. MIT license at least means you can.
  • The 2016 baseline is the real problem, not the PHP code. The Maps JavaScript API has moved substantially since: API keys are mandatory (no key → "For development purposes only" watermark), AdvancedMarkerElement / Map ID are the modern marker path, and several legacy behaviors are deprecated. This library emits the 2016-era google.maps.Marker API. It still works today, but you're building on a deprecation clock you didn't set.
  • API key restrictions bite. If you restrict the key by HTTP referrer, the map renders on the page but every tile request 403s — you get a grey box with no console error unless you open the network tab. Also enable Maps JavaScript API specifically; a key with only Geocoding enabled will fail silently in the same way.
  • CSP: the helper injects inline <script>. If you run a script-src policy without 'unsafe-inline', the map will not initialize. Either allow inline scripts for that route or extract the rendered JS into an external file — the latter is brittle because the generated code references generated variables.
  • Blade double-escaping is the #1 first-hour bug. {{ $mapHtml }} renders literal <div> text. Use {!! !!} and be aware you're now trusting the library's output (fine, it HTML-escapes InfoWindow content — verify that it does for your version).
  • Debugging: the generated JS is a single string with no stack context. When it breaks, dd($mapJs) and read the emitted map_js config object — the failure is almost always a malformed coordinate, an InfoWindow added to a marker but not the map, or a duplicate container id.
  • Coordinates: Coordinate takes lat/lng as floats. If you're feeding it from Eloquent with string-cast columns, cast explicitly — a "51.5" string reaching the serializer produces odd output in older versions.
  • Extension points that actually survive: the library is designed around helper builders (MapHelperBuilder, styles, MarkerClusterer support). Those are usable standalone. The bundle's compiler passes and Twig extensions are not; don't try to port them.
  • Honest recommendation for a new Laravel build: don't adopt this. Use a class-based Blade component + a small GoogleMaps service holding the key and a markers() payload, render with the Maps JS API directly, and keep the markup under your control. Alternatives in the Laravel ecosystem (cornford/googlmapper, farhanwazir/laravelgooglemaps) are largely in the same abandoned state — the JS-API-direct route is the one with no maintenance cliff. Consider this package only if you have an existing Ivory-based codebase to port and need API parity for a migration window.
Weaver

How can I help you explore Laravel packages today?

Conversation history is not saved when not logged in.
Prompt
Add packages to context
No packages found.
diephp/sequences
users-au/socialite-provider
twidpay/twid-logger
mrnewport/laravel-plaid
mrnewport/laravel-repo
mrnewport/laravel-docsign
mrnewport/laravel-stow
mrnewport/laravel-flow
mrnewport/laravel-priceable
mrnewport/laravel-nestedterms
fredmeng/laravel-apidoc-generator
itstructure/laravel-multilingual-tools
pdustdar/elasticsearch
markupai/php-sdk
rlacerda83/lumem-microservice-shipment
uni-method/symfony-lib
tacticmedia/scim-server-bundle
neika-ai/symfony-bundle
mattleads/agent-publishing-bundle
glavweb/framework-bundle