dev-master
9999999-devSymfony2 geocoding bundle
The Requires
by Eric Watts
symfony2 geocode
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