Skip to content

Commit

Permalink
Implemented compatibility with Geocoder 4.0
Browse files Browse the repository at this point in the history
  • Loading branch information
mikebronner committed Jun 18, 2017
1 parent e35aebf commit b38a86d
Show file tree
Hide file tree
Showing 7 changed files with 179 additions and 128 deletions.
8 changes: 8 additions & 0 deletions CHANGELOG.md
Original file line number Diff line number Diff line change
Expand Up @@ -2,6 +2,14 @@
All notable changes to this project will be documented in this file.
This project adheres to [Semantic Versioning](http://semver.org/).

## [2.0.0-RC1] - 18 Jun 2017
### Added
- compatibility with Geocoder 4.0-dev.
- caching to `geocodeQuery()` and `reverseQuery()` methods.

### Updated
- the geocoder `all()` method to be deprecated. Use `get()`.

## [1.1.0] - 17 Jun 2017
### Added
- caching functionality for `geocode()` and `reverse()` methods.
Expand Down
37 changes: 30 additions & 7 deletions README.md
Original file line number Diff line number Diff line change
Expand Up @@ -8,18 +8,21 @@
> If you still use **Laravel 4**, please check out the `0.4.x` branch
[here](https://github.com/geocoder-php/GeocoderLaravel/tree/0.4.x).

**Version 1.0.0 is a backwards-compatibility-breaking update. Please review
**Version 2.0.0 is a backwards-compatibility-breaking update. Please review
this documentation, especially the _Usage_ section before installing.**

This package allows you to use [**Geocoder**](http://geocoder-php.org/Geocoder/)
in [**Laravel 5**](http://laravel.com/).

## Requirements
- PHP >= 7.0.0
- Laravel >= 5.0

## Installation
1. Install the package via composer:
```sh
composer require toin0u/geocoder-laravel
```
_Once 1.0.0 is stable, we will update this command to reflect that. In the interest of getting it out and into your hands, a temporary RC build is best._

2. Find the `providers` array key in `config/app.php` and register the **Geocoder Service Provider**:
```php
Expand All @@ -29,6 +32,31 @@ composer require toin0u/geocoder-laravel
```

## Upgrading
### 1.x to 2.x
The one change to keep in mind here is that the results returned from
`Geocoder for Laravel` are now using the Laravel-native Collections class
instead of returning and instance of `AddressCollection`. This should provide
greater versatility in manipulation of the results, and be inline with
expectations for working with Laravel. The existing `AddressCollection`
methods should map strait over to Laravel's `Collection` methods. But be sure
to double-check your results, if you have been using `getIterator()`, `count()`,
`first()`, `isEmpty()`, `slice()`, `has()`, `get()`, or `all()` on your results.

**Alert:** if you have been using the `getIterator()` method, it is no longer
needed. Simply iterate over your results as you would any other Laravel
collection.

**Deprecated:** the `all()` method on the geocoder is being deprecated in favor
of using `get()`, which will return a Laravel Collection. You can then run
`all()` on that. This method will be removed in version 3.0.0.

**Added:** this version introduces a new way to create more complex queries:
- geocodeQuery()
- reverseQuery()
Please see the [Geocoder documentation](https://github.com/geocoder-php/Geocoder)
for more details.

### 0.x to 1.x
If you are upgrading from a pre-1.x version of this package, please keep the
following things in mind:

Expand Down Expand Up @@ -128,11 +156,6 @@ The service provider initializes the `geocoder` service, accessible via the
app('geocoder')->geocode('Los Angeles, CA')->get();
```

#### Get Array of Addresses
```php
app('geocoder')->geocode('Los Angeles, CA')->all();
```

#### Reverse-Geocoding
```php
app('geocoder')->reverse(43.882587,-103.454067)->get();
Expand Down
6 changes: 5 additions & 1 deletion composer.json
Original file line number Diff line number Diff line change
Expand Up @@ -24,8 +24,12 @@
],
"require": {
"php": ">=5.4",
"geocoder-php/bing-maps-provider": "dev-master@dev",
"geocoder-php/chain-provider": "dev-master@dev",
"geocoder-php/common-http": "dev-master@dev",
"geocoder-php/free-geoip-provider": "dev-master@dev",
"geocoder-php/google-maps-provider": "dev-master@dev",
"geocoder-php/maxmind-binary-provider": "dev-master@dev",
"guzzlehttp/guzzle": "^6.2",
"illuminate/cache": "~5.0",
"illuminate/support": "~5.0",
Expand Down Expand Up @@ -61,7 +65,7 @@
},
"extra": {
"branch-alias": {
"dev-master": "1.2.0-dev"
"dev-master": "2.0.0-RC1"
}
},
"config": {
Expand Down
40 changes: 16 additions & 24 deletions config/geocoder.php
Original file line number Diff line number Diff line change
Expand Up @@ -2,40 +2,32 @@

/**
* This file is part of the GeocoderLaravel library.
*
* (c) Antoine Corcy <[email protected]>
*
* For the full copyright and license information, please view the LICENSE
* file that was distributed with this source code.
*/

use Http\Adapter\Guzzle6\Client;
// use Geocoder\Provider\Chain;
// use Geocoder\Provider\BingMaps;
// use Geocoder\Provider\FreeGeoIp;
use Geocoder\Provider\GoogleMaps\Model\GoogleAddress;
// use Geocoder\Provider\MaxMindBinary;
use Geocoder\Provider\BingMaps\BingMaps;
use Geocoder\Provider\Chain\Chain;
use Geocoder\Provider\FreeGeoIp\FreeGeoIp;
use Geocoder\Provider\GoogleMaps\GoogleMaps;

return [
'cache-duraction' => 999999999,
'providers' => [
// Chain::class => [
// GoogleMaps::class => [
// 'en',
// 'us',
// true,
// env('GOOGLE_MAPS_API_KEY'),
// ],
// FreeGeoIp::class => [],
// ],
// BingMaps::class => [
// 'en-US',
// env('BING_MAPS_API_KEY'),
// ],
GoogleAddress::class => [
'en',
Chain::class => [
GoogleMaps::class => [
'en-US',
env('GOOGLE_MAPS_API_KEY'),
],
FreeGeoIp::class => [],
],
BingMaps::class => [
'en-US',
env('BING_MAPS_API_KEY'),
],
GoogleMaps::class => [
'us',
true,
env('GOOGLE_MAPS_API_KEY'),
],
],
Expand Down
97 changes: 73 additions & 24 deletions src/ProviderAndDumperAggregator.php
Original file line number Diff line number Diff line change
@@ -1,10 +1,11 @@
<?php namespace Geocoder\Laravel;

/**
* This file is part of the Geocoder package.
* This file is part of the Geocoder Laravel package.
* For the full copyright and license information, please view the LICENSE
* file that was distributed with this source code.
*
* @author Mike Bronner <[email protected]>
* @license MIT License
*/

Expand All @@ -14,36 +15,37 @@
use Geocoder\Dumper\Wkb;
use Geocoder\Dumper\Wkt;
use Geocoder\Geocoder;
use Geocoder\Query\GeocodeQuery;
use Geocoder\Query\ReverseQuery;
use Geocoder\Laravel\Exceptions\InvalidDumperException;
use Geocoder\Laravel\ProviderAndDumperAggregator;
use Geocoder\ProviderAggregator;
use Geocoder\Model\AddressCollection;
use Illuminate\Support\Collection;

/**
* @author Mike Bronner <[email protected]>
*/
class ProviderAndDumperAggregator
{
protected $results;
protected $aggregator;
protected $results;

public function __construct(int $limit = Geocoder::DEFAULT_RESULT_LIMIT)
{
$this->aggregator = new ProviderAggregator($limit);
$this->results = collect();
}

/**
* @deprecated Use `get()` instead.
*/
public function all() : array
{
return $this->results->all();
}

public function get() : AddressCollection
public function get() : Collection
{
return $this->results;
}

public function dump($dumper) : Collection
public function dump(string $dumper) : Collection
{
$dumperClasses = collect([
'geojson' => GeoJson::class,
Expand All @@ -70,29 +72,69 @@ public function dump($dumper) : Collection
});
}

public function geocodeQuery($query)
public function geocodeQuery(GeocodeQuery $query) : self
{
return $this->aggregator->geocodeQuery($query);
$cacheKey = serialize($query);
$this->results = cache()->remember(
"geocoder-{$cacheKey}",
config('geocoder.cache-duraction', 0),
function () use ($query) {
$addresses = collect();
$addressCollection = $this->aggregator->geocodeQuery($query);

foreach ($addressCollection as $address) {
$addresses->push($address);
}

return $addresses;
}
);

return $this;
}

public function reverseQuery($query)
public function reverseQuery(ReverseQuery $query) : self
{
return $this->aggregator->reverseQuery($query);
$cacheKey = serialize($query);
$this->results = cache()->remember(
"geocoder-{$cacheKey}",
config('geocoder.cache-duraction', 0),
function () use ($query) {
$addresses = collect();
$addressCollection = $this->aggregator->reverseQuery($query);

foreach ($addressCollection as $address) {
$addresses->push($address);
}

return $addresses;
}
);

return $this;
}

public function getName()
public function getName() : string
{
return $this->aggregator->getName();
}

public function geocode(string $value) : self
{
$cacheId = str_slug($value);
$cacheKey = str_slug($value);
$this->results = cache()->remember(
"geocoder-{$cacheId}",
"geocoder-{$cacheKey}",
config('geocoder.cache-duraction', 0),
function () use ($value) {
return $this->aggregator->geocode($value);

$addresses = collect();
$addressCollection = $this->aggregator->geocode($value);

foreach ($addressCollection as $address) {
$addresses->push($address);
}

return $addresses;
}
);

Expand All @@ -106,47 +148,54 @@ public function reverse(float $latitude, float $longitude) : self
"geocoder-{$cacheId}",
config('geocoder.cache-duraction', 0),
function () use ($latitude, $longitude) {
return $this->aggregator->reverse($latitude, $longitude);
$addresses = collect();
$addressCollection = $this->aggregator->reverse($latitude, $longitude);

foreach ($addressCollection as $address) {
$addresses->push($address);
}

return $addresses;
}
);

return $this;
}

public function limit($limit)
public function limit(int $limit) : self
{
$this->aggregator->limit($limit);

return $this;
}

public function getLimit()
public function getLimit() : int
{
return $this->aggregator->getLimit();
}

public function registerProvider($provider)
public function registerProvider(string $provider) : self
{
$this->aggregator->registerProvider($provider);

return $this;
}

public function registerProviders($providers = [])
public function registerProviders(array $providers = []) : self
{
$this->aggregator->registerProviders($providers);

return $this;
}

public function using($name)
public function using(string $name) : self
{
$this->aggregator->using($name);

return $this;
}

public function getProviders()
public function getProviders() : array
{
return $this->aggregator->getProviders();
}
Expand Down
Loading

9 comments on commit b38a86d

@Nyholm
Copy link
Member

@Nyholm Nyholm commented on b38a86d Jun 18, 2017

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

You may want to consider using php-http/curl-client instead of php-http/guzzle6-adapter. It is faster.

@mikebronner
Copy link
Member Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Yea, was going off the examples in the readme so far. Will switch over.

@Nyholm
Copy link
Member

@Nyholm Nyholm commented on b38a86d Jun 18, 2017

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Do not forget to use a psr7 implementation. Consider guzzle, zend or slim. They are auto discovered.

@mikebronner
Copy link
Member Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Can you point me to the relevant documentation in geocoder, and what parts of the code here you think it should be added to? By default I'm passing most things through to the Geocoder library. Would it not be handled there?

@Nyholm
Copy link
Member

@Nyholm Nyholm commented on b38a86d Jun 18, 2017

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

The Geocoder itself is HTTP independent. It does not care what HTTP client or PSR7 implementation you are using. We let the user to decide that when installing the package. I see that you do not want to give the user the same flexibility. (Or maybe Im mistaken?)

We use HTTPlug to get this abstraction. Read about it here: http://docs.php-http.org/en/latest/httplug/users.html

I describe this in the docs: https://github.com/geocoder-php/Geocoder#installation

So ideally, you would remove php-http/message, curl-client, guzzle6-adapter and guzzle/psr7 and let the user choose what implementation they want.

@mikebronner
Copy link
Member Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Oh, yes, they can choose whatever they want ... its just that the default configuration comes with the guzzle adaptor right now, or curl adapter once I update it. But they are free to use any adaptor they want according to the Geocoder documentation. :)

@mikebronner
Copy link
Member Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I'm trying to read up more on the auto-discovery of the adapter. Can you point me to the code where that is happening? That probably should be implemented, having a bit of a hard time figuring that out. Thanks for bearing with me!

@mikebronner
Copy link
Member Author

@mikebronner mikebronner commented on b38a86d Jun 18, 2017

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

So ideally, you would remove php-http/message, curl-client, guzzle6-adapter and guzzle/psr7 and let the user choose what implementation they want.

The only reason they are there now is so that composer can install all the dependencies. Once 4.0 is live I will remove them from composer.json.

Or do I misunderstand? Should I be only using those in my tests? They aren't actually used in the code, other than tests and config file. (I was going off this: geocoder-php/Geocoder#684 to get it working.)

@Nyholm
Copy link
Member

@Nyholm Nyholm commented on b38a86d Jun 19, 2017

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Can you point me to the code where that is happening?

Oh, that is right, We do not auto discover clients, only message factory:
https://github.com/geocoder-php/Geocoder/blob/master/src/Http/Provider/AbstractHttpProvider.php#L96

The only reason they are there now is so that composer can install all the dependencies. Once 4.0 is live I will remove them from composer.json.

In your composer.json require:

No implementation of HTTP clients, PSR7 or php-http/message.

In your composer.json require-dev:

You should have a HTTP client, PSR7 and http-php/message because you want to be able to run the tests. Which PSR7 and HTTP client you choose does not matter.


Since we require virtual packages a user cannot install willdurand/geocoder without having a client installed. That is why we should suggest a command in the readme which includes a client, psr7 implementation and php-http/message.

When 4.0 is released I will update the readme to say:

$ composer require geocoder-php/google-maps-provider php-http/guzzle6-adapter php-http/message

(I was going off this: geocoder-php/Geocoder#684 to get it working.)

This is unrelated. He was downloading 3.3 and read the docs for master. I moved that class.

Please sign in to comment.