tec4 / geocode-bundle
Symfony2 geocoding bundle
Installs: 160
Dependents: 0
Suggesters: 0
Security: 0
Stars: 0
Watchers: 1
Forks: 0
Open Issues: 0
Type:symfony-bundle
Requires
- php: >=5.3.0
- symfony/framework-bundle: ^2.8 || ^3.0 || ^4.0
- willdurand/geocoder-bundle: @stable
This package is auto-updated.
Last update: 2025-03-29 00:31:27 UTC
README
This bundle provides a wrapper around the BazingaGeocoderBundle. It provides a simple way to implement latitude/longitude coordinates in to your doctrine models.
Installation
Step 1: Download the Bundle
Open a command console, enter your project directory and execute the following command to download the latest stable version of this bundle:
$ composer require tec4/geocode-bundle
This command requires you to have Composer installed globally, as explained in the installation chapter of the Composer documentation.
Step 2: Enable the Bundle
Then, enable the bundle by adding the following line in the app/AppKernel.php
file of your project:
<?php // app/AppKernel.php // ... class AppKernel extends Kernel { public function registerBundles() { $bundles = array( // ... new Tec4\GeocodeBundle\Tec4GeocodeBundle(), ); // ... } // ... }
Also install BazingaGeocoderBundle per their documentation.
Step 3: Implement interface on Model
Add interface to your model (entity/document).
Use pre-created traits if you desire to get most of the required properties and attriubtes for interface.
Must implement new method called getGeocodeableName in code
<?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; } }
Usage
Auto-update entities when certain fields change or if entity has yet to be geocoded
For more info read symfony's docs about registering event listeners and subscribers
<?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:
# 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 }
Batch update via command
All options, except the arguemnt are optional. The class name, however, is required.
php app/console tec4:geocode "Acme\\SomeBundle\\Model\\ClasName" --limit=100 --geocode_provider="google_maps"
TODO
- Add better logging (ability to extend logger and implement own solution/channel to log to, etc)