A Google Maps API package for Laravel built on Ports and Adapters (Hexagonal Architecture) — clean, testable, and designed to grow with your needs.
Most Google Maps packages for Laravel expose raw arrays and mix API calls directly into your business logic. This package takes a different approach:
- Ports and Adapters — your domain code never talks to Google directly; it depends on interfaces
- Typed DTOs —
readonlyclasses with full IDE autocomplete, no more guessing array keys - Built-in cache strategy — configurable TTL per use case to save money on API calls
- Facade + DI — use whichever style fits your team
composer require sysborg/gmaps-laravelPublish the config:
php artisan vendor:publish --provider="Sysborg\GmapsLaravel\GmapsServiceProvider" --tag="gmaps-config"Add your API key to .env:
GOOGLE_MAPS_API_KEY=your_key_hereMake sure the Places API is enabled in your Google Cloud Console.
Find all locations within a radius from a geographic point.
Via Facade:
use Sysborg\GmapsLaravel\Facades\GMap;
use Sysborg\GmapsLaravel\DTOs\Coordinate;
$response = GMap::nearbySearch(
coordinate: new Coordinate(-23.5505, -46.6333),
radius: 1500, // meters
type: 'restaurant', // optional
keyword: 'pizza', // optional
);
foreach ($response->places as $place) {
echo $place->name; // "Pizzaria Italia"
echo $place->vicinity; // "Rua Augusta, 100"
echo $place->rating; // 4.5
echo $place->location->latitude;
echo $place->location->longitude;
}
if ($response->hasNextPage()) {
// fetch next page using $response->nextPageToken
}Via Dependency Injection:
use Sysborg\GmapsLaravel\UseCases\Places\NearbySearchUseCase;
use Sysborg\GmapsLaravel\DTOs\Coordinate;
use Sysborg\GmapsLaravel\DTOs\Places\NearbySearchRequest;
class FindNearbyRestaurantsAction
{
public function __construct(private readonly NearbySearchUseCase $useCase) {}
public function handle(float $lat, float $lng): array
{
$response = $this->useCase->execute(new NearbySearchRequest(
coordinate: new Coordinate($lat, $lng),
radius: 1500,
type: 'restaurant',
));
return $response->toArray();
}
}Every API call is cached by default. The cache key is a deterministic hash of all request parameters — same input always hits the cache.
# Toggle cache on/off
GOOGLE_MAPS_CACHE_ENABLED=true
# Use any Laravel cache driver
GOOGLE_MAPS_CACHE_DRIVER=redis
# TTL per use case (seconds)
GOOGLE_MAPS_CACHE_NEARBY_TTL=3600Full config reference at config/gmaps.php.
src/
├── Contracts/ ← Ports (pure PHP interfaces, zero framework imports)
│ ├── Cache/CachePort.php
│ ├── Http/HttpClientPort.php
│ └── Places/PlacesPort.php
├── DTOs/ ← Immutable readonly value objects
│ ├── Coordinate.php
│ └── Places/ NearbySearchRequest, PlaceResult, NearbySearchResponse
├── UseCases/ ← Application layer (depends only on Ports + DTOs)
│ └── Places/NearbySearchUseCase.php
├── Adapters/ ← Infrastructure (implements Ports using Laravel/Guzzle)
│ ├── Cache/LaravelCacheAdapter.php
│ ├── Http/LaravelHttpAdapter.php
│ └── Places/GooglePlacesAdapter.php
├── Facades/GMap.php
└── GmapsServiceProvider.php
composer install
./vendor/bin/phpunitAll tests use Http::fake() — no real API calls are made.
OK (11 tests, 30 assertions)
| Feature | Status |
|---|---|
| Places — Nearby Search | ✅ |
| Cache with TTL per use case | ✅ |
| Facade + DI integration | ✅ |
| Typed DTOs (readonly) | ✅ |
| PHPUnit tests with Http::fake() | ✅ |
This package is built to grow. The architecture makes it straightforward to add new APIs without touching existing code. If you need any of the below — or something not listed — open an issue and describe your use case. Contributions are welcome.
| Feature | Notes |
|---|---|
| Places — Text Search | Search by keyword anywhere |
| Places — Place Details | Full details by place_id |
| Places — Autocomplete | For address/search inputs |
| Geocoding API | Address ↔ coordinates |
| Reverse Geocoding | Coordinates → formatted address |
| Directions API | Routes with waypoints |
| Distance Matrix | Multi-origin/destination travel time |
| Static Maps | Generate map image URLs |
| Elevation API | Altitude for coordinates |
| Time Zone API | Timezone from coordinates |
| Roads API | Snap-to-road, speed limits |
| Pagination helper | Auto-fetch next pages |
| Multi-page collector | Merge all paginated results automatically |
Have a specific need? Open an issue describing what you need and how you plan to use it. The more context you give, the faster it gets implemented.
- Fork the repository
- Create a branch:
git checkout -b feat/your-feature - Follow the existing patterns — one port, one adapter, one use case (see
docs/plan/architecture.md) - Write tests with
Http::fake() - Open a PR
If this package saves you time or reduces your Google Maps API costs, consider buying a coffee. It helps keep this maintained and motivates new features to be added.
MIT © Anderson Arruda