Integration of the Geocoder library into Symfony.
Our documentation has the following sections:
- Index (This page)
- Public services (Providers)
- Registering Your Own Provider
- All about Cache
- Plugins
- Doctrine support
To install this bundle you need to know how to install the geocoder and providers and then you may just install the bundle like normal:
composer require willdurand/geocoder-bundle:^5.0If you don't use Symfony Flex, you must enable the bundle manually in the application:
// config/bundles.php
// in older Symfony apps, enable the bundle in app/AppKernel.php
return [
// ...
Bazinga\GeocoderBundle\BazingaGeocoderBundle::class => ['all' => true],
];The bundle helps you register your providers and to enable profiling support. To
configure a provider you must use a ProviderFactory. See the following example
using Google Maps.
bazinga_geocoder:
providers:
acme:
factory: Bazinga\GeocoderBundle\ProviderFactory\GoogleMapsFactoryThis will create a service named bazinga_geocoder.provider.acme which is a
GoogleMapsProvider.
You can also configure all ProviderFactories to adjust the behavior of the
provider.
bazinga_geocoder:
providers:
acme:
factory: Bazinga\GeocoderBundle\ProviderFactory\GoogleMapsFactory
cache: 'any.psr16.service'
cache_lifetime: 3600
aliases:
- my_geocoderThis will create a service named my_geocoder that caches the responses for one
hour.
Most ProviderFactories do also take an array with options. This is usually
parameters to the constructor of the provider. In the example of Google Maps:
bazinga_geocoder:
providers:
acme:
factory: Bazinga\GeocoderBundle\ProviderFactory\GoogleMapsFactory
options:
http_client: '@any.psr18.client'
region: 'Sweden'
api_key: 'xxyy'Someone was thinking ahead here. Wouldn't it be nice if you could pass your request through different ProviderFactories? You can!! With the ChainFactory, see the configuration below.
bazinga_geocoder:
providers:
acme:
aliases:
- my_geocoder
cache: 'any.psr16.service'
cache_lifetime: 3600
factory: Bazinga\GeocoderBundle\ProviderFactory\GoogleMapsFactory
options:
api_key: 'xxxx'
acme_ii:
aliases:
- my_geocoder_ii
factory: Bazinga\GeocoderBundle\ProviderFactory\TomTomFactory
options:
api_key: 'xxyy'
http_client: '@any.psr18.client'
region: 'Sweden'
chain:
factory: Bazinga\GeocoderBundle\ProviderFactory\ChainFactory
options:
services: ['@bazinga_geocoder.provider.acme', '@bazinga_geocoder.provider.acme_ii']The services key could also be as follows services: ['@my_geocoder', '@my_geocoder_ii']. Notice these are the values from the aliases key.
If you're using autowiring you can use bindings provided the bundle.
bazinga_geocoder:
providers:
googleMaps:
factory: Bazinga\GeocoderBundle\ProviderFactory\GoogleMapsFactory<?php
namespace App\Service;
use Geocoder\Provider\Provider;
class MyService
{
private $googleMapsGeocoder;
public function __construct(Provider $googleMapsGeocoder)
{
$this->googleMapsGeocoder = $googleMapsGeocoder;
}
}Each configured provider has a binding in the following format:
providerName + Geocoder.
In the example we configured provider name as googleMaps so the argument is $googleMapsGeocoder.
You can fake your local IP through this bundle in order to get location information in your development environment, for instance:
/**
* @Template()
*/
public function indexAction(Request $request)
{
// Retrieve information from the current user (by its IP address)
$result = $this->container
->get('bazinga_geocoder.provider.acme')
->geocodeQuery(GeocodeQuery::create($request->server->get('REMOTE_ADDR')));
// Find the 5 nearest objects (15km) from the current user.
$coords = $result->first()->getCoordinates();
$objects = ObjectQuery::create()
->filterByDistanceFrom($coords->getLatitude(), $coords->getLongitude(), 15)
->limit(5)
->find();
return array(
'geocoded' => $result,
'nearest_objects' => $objects
);
}In the example above, we'll retrieve information from the user's IP address, and 5
objects nears him.
But it won't work on your local environment, that's why this bundle provides
an easy way to fake this behavior by using a fake_ip configuration.
# config/packages/bazinga_geocoder.yaml
when@dev:
bazinga_geocoder:
fake_ip: 123.123.123.123If set, the parameter will replace all instances of "127.0.0.1" in your queries and replace them with the given one.
If you'd like to replace other ip instead of "127.0.0.1" (e.g. when using localhost inside a VM) you can set the optional local_ip parameter:
when@dev:
bazinga_geocoder:
fake_ip:
local_ip: 192.168.99.1 # default 127.0.0.1
ip: 123.123.123.123You can also let Faker generate fake ip for you.
when@dev:
bazinga_geocoder:
fake_ip:
use_faker: true # default falseSometimes you have to cache the results from a provider. For this case the bundle provides simple configuration. You only need to provide a service name for you SimpleCache (PSR-16) service and you are good to go.
bazinga_geocoder:
providers:
acme:
factory: Bazinga\GeocoderBundle\ProviderFactory\GoogleMapsFactory
cache: 'any.psr16.service'
cache_lifetime: 3600Read more about cache here.
If you need to dump your geocoded data to a specific format, you can use the Dumper component. The following dumper's are supported:
- GeoArray
- GeoJson
- GPX
- KML
- WKB
- WKT
Here is an example if you are using autowiring:
<?php
namespace App\Controller;
use Geocoder\Dumper\GeoJson;
use Geocoder\Provider\Provider;
use Geocoder\Query\GeocodeQuery;
use Symfony\Component\HttpFoundation\JsonResponse;
use Symfony\Component\HttpFoundation\Request;
class AcmeController
{
private $acmeGeocoder;
private $geoJsonDumper;
public function __construct(Provider $acmeGeocoder, GeoJson $dumper)
{
$this->acmeGeocoder = $acmeGeocoder;
$this->geoJsonDumper = $dumper;
}
public function geocodeAction(Request $request)
{
$result = $this->acmeGeocoder->geocodeQuery(GeocodeQuery::create($request->server->get('REMOTE_ADDR')));
$body = $this->geoJsonDumper->dump($result);
return new JsonResponse($body);
}
}Each dumper service if it implements Geocoder\Dumper\Dumper interface will be
tagged with bazinga_geocoder.dumper tag. Each dumper can be used with autowiring
providing the dumper class name as the argument.
Also If you want to inject all the tagged dumpers to your service you can provide
your service argument as: !tagged bazinga_geocoder.dumper.
The HTTP geocoder allows to use any PSR-18 compatible client.
In Symfony apps it is recommended to use symfony/http-client, but if you want to use Guzzle,
just require it in your dependencies:
composer require guzzlehttp/guzzle http-interop/http-factory-guzzleAnd configure your provider to use it:
services:
guzzle.client:
class: GuzzleHttp\Client
bazinga_geocoder:
providers:
acme:
factory: ...
options:
http_client: '@guzzle.client'You'll find the reference configuration below:
# config/packages/bazinga_geocoder.yaml
bazinga_geocoder:
profiling:
enabled: ~ # Default is same as kernel.debug
fake_ip:
enabled: true
ip: null
providers:
# ...
acme:
factory: ~ # Required
cache: 'app.cache'
cache_lifetime: 3600
cache_precision: 4 # Precision of the coordinates to cache.
limit: 5
locale: 'sv'
logger: 'logger'
plugins:
- my_custom_plugin
aliases:
- acme
- acme_geocoder
options:
foo: bar
biz: baz
# ...
free_chain:
aliases:
- free_geo_chain
factory: Bazinga\GeocoderBundle\ProviderFactory\ChainFactory
options:
services: ['@acme', '@acme_ii']The BazingaGeocoderBundle is just a Symfony integration for Geocoder-PHP and it does not have any classes which falls under the BC promise. The backwards compatibility of the bundle is only the configuration and its values (and of course the behavior of those values).
The public service names (excluding the ones related to profiling/DataCollector) falls under the backwards compatibility promise.
Bottom line is, that you can trust that your configuration will not break and that the services you use will still be working.
Setup the test suite using Composer:
composer update
composer test