Install the Bundle
Add to composer.json:
"require": {
"antwebes/geocoder-bundle": "2.4.*@dev"
}
Run composer update.
Enable the Bundle
In config/bundles.php:
return [
// ...
Bazinga\GeocoderBundle\BazingaGeocoderBundle::class => ['all' => true],
];
Configure Providers
Define geocoding providers in config/packages/bazinga_geocoder.yaml:
bazinga_geocoder:
providers:
google_maps:
http_client: http_client
key: "%env(GOOGLE_MAPS_API_KEY)%"
host: "https://maps.googleapis.com"
First Use Case: Geocoding an Address
Inject the Geocoder service and use it in a controller:
use Bazinga\GeocoderBundle\Geocoder\GeocoderManager;
use Geocoder\Provider\GoogleMaps\GoogleMapsUnit;
class LocationController extends AbstractController
{
public function index(GeocoderManager $geocoder)
{
$address = '1600 Amphitheatre Parkway, Mountain View, CA';
$geocode = $geocoder->geocode($address, 'google_maps');
foreach ($geocode as $hit) {
$coordinates = $hit->getCoordinates();
return $this->json($coordinates);
}
}
}
Reverse Geocoding Convert coordinates to human-readable addresses:
$coordinates = [40.714224, -73.961452];
$reverse = $geocoder->reverse($coordinates, 'google_maps');
Batch Processing
Use GeocoderManager to iterate over multiple addresses:
$addresses = ['Address 1', 'Address 2'];
foreach ($addresses as $address) {
$geocode = $geocoder->geocode($address, 'google_maps');
// Process results...
}
Fallback Providers Configure multiple providers with fallback logic:
bazinga_geocoder:
providers:
primary:
provider: google_maps
fallback:
provider: bing_maps
key: "%env(BING_MAPS_API_KEY)%"
Then use:
$geocoder->geocode($address, 'primary', ['fallback' => 'fallback']);
Caching Results Cache geocoding results to reduce API calls:
bazinga_geocoder:
providers:
google_maps:
cache: cache.app
ttl: 3600 # Cache for 1 hour
Symfony Forms: Use GeocoderType for address fields:
use Bazinga\GeocoderBundle\Form\Type\GeocoderType;
$builder->add('address', GeocoderType::class, [
'provider' => 'google_maps',
'error_bubbling' => true,
]);
Doctrine Entities: Add geocoding to entity lifecycle:
use Bazinga\GeocoderBundle\Geocoder\GeocoderManager;
class LocationEntity
{
public function __construct(GeocoderManager $geocoder)
{
$this->geocoder = $geocoder;
}
public function setAddress($address)
{
$this->address = $address;
$this->geocode();
}
private function geocode()
{
$geocode = $this->geocoder->geocode($this->address, 'google_maps');
if ($geocode) {
$this->coordinates = $geocode->first()->getCoordinates();
}
}
}
Command-Line Geocoding: Create a custom command:
use Bazinga\GeocoderBundle\Geocoder\GeocoderManager;
use Symfony\Component\Console\Command\Command;
use Symfony\Component\Console\Input\InputInterface;
use Symfony\Component\Console\Output\OutputInterface;
class GeocodeCommand extends Command
{
protected static $defaultName = 'app:geocode';
public function __construct(private GeocoderManager $geocoder)
{
parent::__construct();
}
protected function execute(InputInterface $input, OutputInterface $output): int
{
$address = $input->getArgument('address');
$result = $this->geocoder->geocode($address, 'google_maps');
$output->writeln(json_encode($result));
return Command::SUCCESS;
}
}
Provider Compatibility
antwebes/geocoder (v2.4), not the original geocoder-php/Geocoder. Ensure you’re using the correct package:
composer require antwebes/geocoder:^2.4
geocoder-php/Geocoder directly.API Key Management
config/packages/bazinga_geocoder.yaml is insecure. Always use environment variables:
key: "%env(GOOGLE_MAPS_API_KEY)%"
Rate Limiting
try {
$geocode = $geocoder->geocode($address, 'google_maps');
} catch (\Geocoder\Exception\UnsupportedProviderException $e) {
$geocode = $geocoder->geocode($address, 'fallback');
}
Coordinate Precision
40.714224 vs. 40.7142). Normalize results:
$coordinates = $hit->getCoordinates();
$normalized = [
round($coordinates->getLatitude(), 6),
round($coordinates->getLongitude(), 6),
];
Symfony 5+ Deprecations
geocoder-php/GeocoderBundle instead.Enable Debugging
Add this to config/packages/bazinga_geocoder.yaml to log requests:
bazinga_geocoder:
providers:
google_maps:
debug: true
Logs will appear in var/log/dev.log.
Common Errors
| Error | Solution |
|---|---|
UnsupportedProviderException |
Verify the provider name matches config/packages/bazinga_geocoder.yaml. |
HttpException (403 Forbidden) |
Check API key validity or quota limits. |
InvalidArgumentException |
Ensure the address string is non-empty and properly formatted. |
CacheException |
Verify Doctrine Cache is configured (cache.app must exist). |
Custom Providers Extend the bundle to support non-standard providers:
use Bazinga\GeocoderBundle\Provider\ProviderInterface;
class CustomProvider implements ProviderInterface
{
public function geocode($address)
{
// Custom logic
}
public function reverse($coordinates)
{
// Custom logic
}
}
Register in services.yaml:
services:
app.custom_provider:
class: App\Geocoder\CustomProvider
tags:
- { name: bazinga_geocoder.provider, alias: custom }
Event Listeners
Listen to geocoding events (e.g., GeocoderEvent):
use Bazinga\GeocoderBundle\Event\GeocoderEvent;
use Symfony\Component\EventDispatcher\EventSubscriberInterface;
class GeocoderSubscriber implements EventSubscriberInterface
{
public static function getSubscribedEvents()
{
return [
'bazinga_geocoder.geocode' => 'onGeocode',
];
}
public function onGeocode(GeocoderEvent $event)
{
// Modify results or log requests
}
}
HTTP Client Customization Override the default HTTP client
How can I help you explore Laravel packages today?