dev-master
9999999-devSymfony2 geocoding bundle
The Requires
by Eric Watts
symfony2 geocode
Wallogit.com
2017 © Pedro Peláez
Symfony2 geocoding bundle
This bundle provides a wrapper around the BazingaGeocoderBundle. It provides a simple way to implement latitude/longitude coordinates in to your doctrine models., (*1)
Open a command console, enter your project directory and execute the following command to download the latest stable version of this bundle:, (*2)
$ composer require tec4/geocode-bundle
This command requires you to have Composer installed globally, as explained in the installation chapter of the Composer documentation., (*3)
Then, enable the bundle by adding the following line in the app/AppKernel.php
file of your project:, (*4)
<?php
// app/AppKernel.php
// ...
class AppKernel extends Kernel
{
public function registerBundles()
{
$bundles = array(
// ...
new Tec4\GeocodeBundle\Tec4GeocodeBundle(),
);
// ...
}
// ...
}
Also install BazingaGeocoderBundle per their documentation., (*5)
Add interface to your model (entity/document)., (*6)
Use pre-created traits if you desire to get most of the required properties and attriubtes for interface., (*7)
Must implement new method called getGeocodeableName in code, (*8)
<?php
namespace Acme\SomeBundle\Model;
use Tec4\GeocodeBundle\Model\GeocodeableInterface;
use Tec4\GeocodeBundle\Model\GeocodeableTraits;
class NewClass implements GeocodeableInterface
{
/**
* Include properties and accessors for geocoding
*/
use GeocodeableTraits;
// ...
private $address;
// ...
/**
* {@inheridoc}
*/
public function getGeocodeableName()
{
// Return some geocodeable, perhaps something like: $this->getAddress();
// Example location would be: 1234 Some Street #1, Some City, Some State
// Can be any geocodeable location
return $this->address;
}
}
For more info read symfony's docs about registering event listeners and subscribers, (*9)
<?php
namespace Acme\SomeBundle\EventListener;
use Doctrine\Common\EventSubscriber;
use Doctrine\ORM\Event\LifecycleEventArgs;
use Bazinga\Bundle\GeocoderBundle\Geocoder\LoggableGeocoder;
use Tec4\GeocodeBundle\Model\GeocodeableInterface;
use Tec4\GeocodeBundle\Service\ModelGeocoder;
/**
* Hook into Doctrine prePersist & preUpdate events
* to update geocode specific fields if information
* about an entity's location has changed.
*/
class GeocodeEntitySubscriber implements EventSubscriber
{
/** @var LoggableGeocoder $geocoder */
private $geocoder;
/** @var ModelGeocoder $modelGeocoder */
private $modelGeocoder;
/**
* @param LoggableGeocoder $geocoder
* @param ModelGeocoder $modelGeocoder
*/
public function __construct(LoggableGeocoder $geocoder, ModelGeocoder $modelGeocoder)
{
$this->geocoder = $geocoder;
$this->modelGeocoder = $modelGeocoder;
}
public function getSubscribedEvents()
{
return array(
'prePersist',
'preUpdate',
);
}
/**
* Geocode entity if it has not already been done
*
* @param LifecycleEventArgs $args
*/
public function prePersist(LifecycleEventArgs $args)
{
if (($entity = $args->getEntity()) instanceof GeocodeableInterface) {
if (!$entity->isGeocoded()) {
$this->geocode($entity);
}
}
}
/**
* Geocode entity if has yet to be done or if location has changed
*
* @param LifecycleEventArgs $args
*/
public function preUpdate(LifecycleEventArgs $args)
{
if (($entity = $args->getEntity()) instanceof GeocodeableInterface) {
if (!$entity->isGeocoded() || $args->hasChangedField('address')) {
$this->geocode($entity);
// Need to recompute changeset to update correctly
$em = $args->getEntityManager();
$uow = $em->getUnitOfWork();
$meta = $em->getClassMetadata(get_class($entity));
$uow->recomputeSingleEntityChangeSet($meta, $entity);
}
}
}
/**
* Handle geocoding of entity
*
* @param GeocodeableInterface $entity
*/
public function geocode(GeocodeableInterface $entity)
{
try {
$this->modelGeocoder->updateModel($entity, $this->geocoder, true);
} catch (\Exception $e) {
// Perhaps do something here
// Add message to flash bag?
}
}
}
Configure service:, (*10)
# src/Acme/SomeBundle/Resources/config/services.yml
services:
acme.listener.geocode_entities:
class: Acme\SomeBundle\EventListener\GeocodeEntitySubscriber
arguments:
- @bazinga_geocoder.geocoder
- @tec4_geocode.model_geocoder
tags:
- { name: doctrine.event_subscriber, connection: default }
All options, except the arguemnt are optional. The class name, however, is required., (*11)
php app/console tec4:geocode "Acme\\SomeBundle\\Model\\ClasName" --limit=100 --geocode_provider="google_maps"
Symfony2 geocoding bundle
symfony2 geocode