PHPackages                             daa/addressable-bundle - PHPackages - PHPackages  [Skip to content](#main-content)[PHPackages](/)[Directory](/)[Categories](/categories)[Trending](/trending)[Leaderboard](/leaderboard)[Changelog](/changelog)[Analyze](/analyze)[Collections](/collections)[Log in](/login)[Sign up](/register)

1. [Directory](/)
2. /
3. [API Development](/categories/api)
4. /
5. daa/addressable-bundle

ActiveSymfony-bundle[API Development](/categories/api)

daa/addressable-bundle
======================

Symfony bundle to make entities addressable and geo spacial services for searching and comparing their latitude/longitude

0.6.0(4y ago)612.8k10[1 issues](https://github.com/danielanteloagra/AddressableBundle/issues)PHPPHP &gt;=5.4

Since Jan 7Pushed 2y ago2 watchersCompare

[ Source](https://github.com/danielanteloagra/AddressableBundle)[ Packagist](https://packagist.org/packages/daa/addressable-bundle)[ RSS](/packages/daa-addressable-bundle/feed)WikiDiscussions master Synced yesterday

READMEChangelog (10)Dependencies (7)Versions (12)Used By (0)

[![Build Status](https://camo.githubusercontent.com/36bce06002930cc1d9cb18685b9a90457f9acea0e7a2625b8caa53c3da8aea85/68747470733a2f2f6170692e7472617669732d63692e6f72672f64616e69656c616e74656c6f2f4164647265737361626c6542756e646c652e7376673f6272616e63683d6d6173746572)](https://travis-ci.org/danielantelo/AddressableBundle)

Symfony Addressable Bundle
==========================

[](#symfony-addressable-bundle)

This is a Symfony bundle which facilitates making entities addressable and geo location aware.

It includes a google map form type to search for and set addresses (with lat/lng), and a geo spatial service to ease calculating distances, sorting and filtering within a radius, etc using these objects with latitude and longitude.

Installation Symfony 5/6
------------------------

[](#installation-symfony-56)

Add the following to composer.json:

```
"require": {
    ...
    "daa/addressable-bundle": "^0.6"
}
```

Register the bundle in your `config/bundles.php`:

```
return [
    ...
    Addressable\Bundle\AddressableBundle::class => ['all' => true]
]
```

Include the twig template for the type layout in `config/packages/twig.yml`

```
twig:
    default_path: '%kernel.project_dir%/templates'
    form_themes:
        - '@Addressable/Form/fields.html.twig'
```

Installation Symfony 2/3
------------------------

[](#installation-symfony-23)

Add the following to composer.json:

```
"require": {
    ...
    "daa/addressable-bundle": "0.5"
}
```

Register the bundle in your `app/AppKernel.php`:

```
new Addressable\Bundle\AddressableBundle(),
```

Include the twig template for the type layout in `app/config/config.yml`

```
twig:
    form_themes:
          - '@Addressable/Form/fields.html.twig' # or AddressableBundle:Form:fields.html.twig in older versions of symfony
```

Usage
-----

[](#usage)

Now your entity or document must:

1. implement the included AddressableInterface
2. use the relevant trait (ORM or PHPCR version) or manually reproduce the required fields, getters and setters

```
    namespace Your\Project\Entity;

    use Addressable\Bundle\Model\AddressableInterface;
    use Addressable\Bundle\Model\Traits\ORM\AddressableTrait;
    # for optional email, tel, fax fields also include and use these
    use Addressable\Bundle\Model\ContactableInterface;
    use Addressable\Bundle\Model\Traits\ORM\ContactableTrait;

    class YourEntity implements AddressableInterface, ContactableInterface
    {
        use AddressableTrait;
        use ContactableTrait;

        /**
         * @ORM\Column(type="text")
         */
        protected $yourOtherField;

        ...
    }
```

Note, if you are using an older version of PHP which does not support traits, then you are forced to copy the trait code manually into your entity.

Once your entity is setup, we can add the address map selector to your forms in the following ways:

```
use Addressable\Bundle\Form\Type\AddressMapType;
use Addressable\Bundle\Form\Type\ContactDetailsType; # optional email, tel, fax

// if you are using standard symfony form type
public function buildForm(FormBuilderInterface $builder, array $options)
{
    $builder
        ->add('address', AddressMapType::class, array(
            'google_api_key' => 'yourKeyHere'
        ))
    ...
}

// if you are using Sonata Admin
protected function configureFormFields(FormMapper $formMapper)
{
    $formMapper
        ->with('Location')
            ->add('address', AddressMapType::class, array(
                'google_api_key' => 'yourKeyHere'
            ))
        ->end()
        ...
}

/**
 * if you are doing it directly in a controller Action
 *
 * @Route("/", name="homepage")
 * @Template("@App/page.html.twig")
 */
public function indexAction(Request $request)
{
    $entity = new AddressableEntity();
    $form = $this->createForm(AddressMapType::class, $entity, array(
        'google_api_key' => 'yourKeyHere'
    ));

    /* or alternatively when using the nested/related versions:
    $form = $this->createFormBuilder($entity)
        ->add('address', AddressMapType::class, array(
            'google_api_key' => 'yourKeyHere'
        ))
        ->add('contactDetails', ContactDetailsType::class)
        ->getForm();
    */

    // replace this example code with whatever you need
    return [
        'form' => $form->createView(),
    ];
}
```

Note: if using address as a child or relation remember to set the 'data\_class' options pointing to the Address object.

Options
-------

[](#options)

We can override several options:

```
->add(
    'address',
     AddressMapType::class,
     array(
        'google_api_key' => 'yourKeyHere',
         'map_width' => '100%',    // the width of the map
         'map_height' => '300px',  // the height of the map
         'default_lat' => 51.5,    // the starting position on the map
         'default_lng' => -0.1245, // the starting position on the map
         'include_current_position_action' => true, // whether to include the set current position button
         'street_number_field' => array(
             'name' => 'streetNumber',
             'type' => 'text',
             'options' => array(
                 'required' => true
             )
         ),
         'street_name_field' => array(
             'name' => 'streetName',
             'type' => 'text',
             'options' => array(
                 'required' => true
             )
         ),
         'city_field' => array(
             'name' => 'city',
             'type' => 'text',
             'options' => array(
                 'required' => true
             )
         ),
         'zipcode_field' => array(
             'name' => 'zipCode',
             'type' => 'text',
             'options' => array(
                 'required' => true
             )
         ),
         'country_field' => array(
             'name' => 'country',
             'type' => 'text',
             'options' => array(
                 'required' => true
             )
         ),
         'latitude_field' => array(
             'name' => 'latitude',
             'type' => 'hidden',
             'options' => array(
                 'required' => false
             )
         ),
         'longitude_field' => array(
             'name' => 'longitude',
             'type' => 'hidden',
             'options' => array(
                 'required' => false
             )
         ),
         'administrative_area_level_1_field' => array(
             'name' => 'administrativeAreaLevel1',
             'type' => 'text',
             'options' => array(
                 'required' => false
             )
         ),
         'administrative_area_level_2_field' => array(
             'name' => 'administrativeAreaLevel2',
             'type' => 'text',
             'options' => array(
                 'required' => false
             )
         )
     )
);

# And same for the optional contact details fields
->add(
    'contactDetails',
    ContactDetailsType:class,
    array(
        'email_field' => array(
            'name' => 'email',
            'type' => TextType::class,
            'options' => array(
                'required' => false
            )
        ),
        'phone_field' => array(
            'name' => 'phoneNumber',
            'type' => TextType::class,
            'options' => array(
                'required' => false
            )
        ),
        'fax_field' => array(
            'name' => 'fax',
            'type' => TextType::class,
            'options' => array(
                'required' => false
            )
        ),
    )
);
```

Country Features
----------------

[](#country-features)

If you use "country" type (Symfony\\Component\\Form\\Extension\\Core\\Type\\CountryType) for the "country\_field" the geospatial helper uses googles returned shortcode to populate the country short code in the dropdown

Further Customization
---------------------

[](#further-customization)

If you don't want the bundle to use it's own script you can override the *address\_map\_scripts* block to be empty; and then simply copy and paste the javascript in vendor/daa/addressable-bundle/Resources/public/js/address\_map.js to your own js files.

To add additional functionality after address updates, simply override the block *address\_map\_callback* and extend to add the additional functionality (or make it empty and define var gmap\_callback in your js code).

```
    {% block address_map_callback %}

            var gmap_callback = function(location, gmap){
                // your callback code here
            }

    {% endblock %}

```

Screenshot
----------

[](#screenshot)

Sonata implementation:

[![View screenshot](https://raw.githubusercontent.com/danielanteloagra/AddressableBundle/master/screenshot.png)](https://raw.githubusercontent.com/danielanteloagra/AddressableBundle/master/screenshot.png)

Geospatial Helper Service
-------------------------

[](#geospatial-helper-service)

From your controller you can get the the *addressable\_bundle.geospatial\_helper* service; from anywhere else you can instantiate the GeospatialHelper class directly.

Examples:

```
  public function symfonyControllerAction()
  {
      $helper = $this->get('addressable_bundle.geospatial_helper');

      $centerPoint = new YourEntity(); // must implement AddressableInterface or GeoPointInterface
      $point1 = new YourEntity(); // must implement AddressableInterface or GeoPointInterface
      $point2 = new YourEntity(); // must implement AddressableInterface or GeoPointInterface
      $points = array($point1, $point2);

      // getting distance in KM between two points
      $distanceInKm = $helper->getDistanceBetweenPoints($point1, $point2);

      // filtering an array of points by radius from a center point
      $pointsWithinRadius = $helper->filterPointsWithinRadius($centerPoint, $points, $radius);

      // sort an array of addressable objects to be ordered by distance from a center point
      $orderedPoints = $helper->sortAroundCenterPoint($centerPoint, $points);
  }

```

###  Health Score

32

—

LowBetter than 69% of packages

Maintenance17

Infrequent updates — may be unmaintained

Popularity30

Limited adoption so far

Community18

Small or concentrated contributor base

Maturity55

Maturing project, gaining track record

 Bus Factor1

Top contributor holds 69% of commits — single point of failure

How is this calculated?**Maintenance (25%)** — Last commit recency, latest release date, and issue-to-star ratio. Uses a 2-year decay window.

**Popularity (30%)** — Total and monthly downloads, GitHub stars, and forks. Logarithmic scaling prevents top-heavy scores.

**Community (15%)** — Contributors, dependents, forks, watchers, and maintainers. Measures real ecosystem engagement.

**Maturity (30%)** — Project age, version count, PHP version support, and release stability.

###  Release Activity

Cadence

Every ~271 days

Recently: every ~524 days

Total

11

Last Release

1477d ago

### Community

Maintainers

![](https://www.gravatar.com/avatar/ed63606fec8f7c8e47b8528c24b96c1f6627274d47f8dec2a0532c8d3c359cce?d=identicon)[danielanteloagra](/maintainers/danielanteloagra)

---

Top Contributors

[![danielantelo](https://avatars.githubusercontent.com/u/9608393?v=4)](https://github.com/danielantelo "danielantelo (29 commits)")[![dmhernandez2525](https://avatars.githubusercontent.com/u/47400105?v=4)](https://github.com/dmhernandez2525 "dmhernandez2525 (5 commits)")[![awesemo](https://avatars.githubusercontent.com/u/1811473?v=4)](https://github.com/awesemo "awesemo (3 commits)")[![nicolasricci](https://avatars.githubusercontent.com/u/208481?v=4)](https://github.com/nicolasricci "nicolasricci (2 commits)")[![comur](https://avatars.githubusercontent.com/u/1212381?v=4)](https://github.com/comur "comur (1 commits)")[![migmolrod](https://avatars.githubusercontent.com/u/5715026?v=4)](https://github.com/migmolrod "migmolrod (1 commits)")[![phiamo](https://avatars.githubusercontent.com/u/207291?v=4)](https://github.com/phiamo "phiamo (1 commits)")

###  Code Quality

TestsPHPUnit

### Embed Badge

![Health badge](/badges/daa-addressable-bundle/health.svg)

```
[![Health](https://phpackages.com/badges/daa-addressable-bundle/health.svg)](https://phpackages.com/packages/daa-addressable-bundle)
```

###  Alternatives

[easycorp/easyadmin-bundle

Admin generator for Symfony applications

4.3k17.9M388](/packages/easycorp-easyadmin-bundle)[symfony/ux-cropperjs

Cropper.js integration for Symfony

19346.6k3](/packages/symfony-ux-cropperjs)[chameleon-system/chameleon-base

The Chameleon System core.

1028.6k5](/packages/chameleon-system-chameleon-base)[2lenet/crudit-bundle

The easy like Crud'it Bundle.

1616.4k14](/packages/2lenet-crudit-bundle)

PHPackages © 2026

[Directory](/)[Categories](/categories)[Trending](/trending)[Changelog](/changelog)[Analyze](/analyze)
