2017 © Pedro Peláez
 

symfony-bundle geocode-bundle

Symfony2 geocoding bundle

image

tec4/geocode-bundle

Symfony2 geocoding bundle

  • Friday, October 14, 2016
  • by tec4
  • Repository
  • 1 Watchers
  • 0 Stars
  • 91 Installations
  • PHP
  • 0 Dependents
  • 0 Suggesters
  • 0 Forks
  • 0 Open issues
  • 1 Versions
  • 1 % Grown

The README.md

Summary

This bundle provides a wrapper around the BazingaGeocoderBundle. It provides a simple way to implement latitude/longitude coordinates in to your doctrine models., (*1)

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:, (*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)

Step 2: Enable the Bundle

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)

Step 3: Implement interface on Model

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;
    }
}

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, (*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 }

Batch update via command

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"

TODO

  1. Add better logging (ability to extend logger and implement own solution/channel to log to, etc)

The Versions

14/10 2016

dev-master

9999999-dev

Symfony2 geocoding bundle

  Sources   Download

The Requires

 

by Eric Watts

symfony2 geocode