Skip to content

Commit

Permalink
Browse files Browse the repository at this point in the history
  • Loading branch information
DivineOmega committed Jul 27, 2021
2 parents b0c45cf + 043d682 commit b5cdc0f
Show file tree
Hide file tree
Showing 8 changed files with 123 additions and 12 deletions.
3 changes: 2 additions & 1 deletion .gitignore
Original file line number Diff line number Diff line change
@@ -1,3 +1,4 @@
/vendor/
composer.lock
.idea
.idea
.DS_Store
34 changes: 33 additions & 1 deletion README.md
Original file line number Diff line number Diff line change
Expand Up @@ -7,7 +7,7 @@ Features:

* Automatic geocoding of addresses on change, provided by the Google Maps API
* Validation of address details (country, postcode)
* Conversation of ISO country code to country name
* Conversion of ISO country code to country name
* Ability to store meta data about addresses - e.g. `['type' => 'delivery', 'name' => 'home_address']`

## Installation
Expand All @@ -32,6 +32,15 @@ Note that by default, you require a Google Maps API key in order to provide
address geocoding and distance calculations. If you do not wish to use geocoding,
this can be disabled in the configuration.

### Strict geocoding

By default, geocoding is configured as "lenient"; if, for example, the name of a real city is given
but the postcode and street address refer to a nonexistent place, it will geocode as the center of
that city.

Set the `geocoding.strict` flag to `true` in the configuration file to instead fail to geocode in
this scenario.

## Usage

Assign the `HasAddresses` trait to the model you wish to have associated addresses.
Expand Down Expand Up @@ -94,6 +103,29 @@ $address->geocode();
$address->save();
```

Note that geocoding can fail, in which case, you can detect that it failed by checking whether the
address is geocoded after attempting geocoding:

```php
$address->geocode();

if (!$address->isGeocoded()) {
// Handle geocoding failure here.
}
```

If there was an existing latitude/longitude set and geocoding fails, these are cleared.

```php
$address->geocode(); // Succeeds

// Change the address details here.

$address->geocode(); // Fails

// Latitude and longitude are now null.
```

### Validation

Validation is automatic when an address is created or updated. You can expect an
Expand Down
2 changes: 1 addition & 1 deletion composer.json
Original file line number Diff line number Diff line change
Expand Up @@ -4,7 +4,7 @@
"type": "library",
"require": {
"php": ">=7.1",
"laravel/framework": "^5.6||^6.0",
"laravel/framework": "^5.6||^6.0||^7.0||^8.0",
"divineomega/php-countries": "^2.1",
"divineomega/php-postcodes": "^4.4",
"langleyfoxall/simple-google-maps": "^1.0",
Expand Down
26 changes: 26 additions & 0 deletions src/Helpers/CountryHelper.php
Original file line number Diff line number Diff line change
@@ -0,0 +1,26 @@
<?php


namespace DivineOmega\LaravelAddresses\Helpers;


use DivineOmega\Countries\Countries;
use DivineOmega\Countries\Country;

abstract class CountryHelper
{
static $countriesByCode = [];

static function getByIsoCode($countryCode): ?Country
{
if (array_key_exists($countryCode, self::$countriesByCode)) {
return self::$countriesByCode[$countryCode];
}

$country = (new Countries())->getByIsoCode($countryCode);

self::$countriesByCode[$countryCode] = $country;

return $country;
}
}
26 changes: 18 additions & 8 deletions src/Models/Address.php
Original file line number Diff line number Diff line change
Expand Up @@ -7,6 +7,7 @@
use DivineOmega\LaravelAddresses\DistanceStrategies\Direct;
use DivineOmega\LaravelAddresses\Exceptions\InvalidCountryException;
use DivineOmega\LaravelAddresses\Exceptions\InvalidUKPostcodeException;
use DivineOmega\LaravelAddresses\Helpers\CountryHelper;
use DivineOmega\LaravelAddresses\Helpers\GoogleMaps;
use DivineOmega\LaravelAddresses\Interfaces\DistanceStrategyInterface;
use DivineOmega\LaravelAddresses\Objects\Location;
Expand Down Expand Up @@ -50,7 +51,7 @@ public function getCountryAttribute(): ?Country
return null;
}

return (new Countries())->getByIsoCode($this->country_code);
return CountryHelper::getByIsoCode($this->country_code);
}

public function getCountryNameAttribute(): ?string
Expand All @@ -72,13 +73,13 @@ public function getHumanReadableAttribute(): string

public function validate(): void
{
if (!$this->country) {
if (config('addresses.validation.country-code') && !$this->country) {
throw new InvalidCountryException();
}

switch ($this->country->isoCodeAlpha3) {
case 'GBR':
if (!Validator::validatePostcode($this->postcode)) {
if (config('addresses.validation.uk-postcode') && !Validator::validatePostcode($this->postcode)) {
throw new InvalidUKPostcodeException();
}
break;
Expand All @@ -91,12 +92,21 @@ public function geocode(): void
return;
}

$latLng = GoogleMaps::instance()
->allowPartialMatches()
->geocode($this->human_readable);
$googleMaps = GoogleMaps::instance();

$this->latitude = $latLng->lat;
$this->longitude = $latLng->long;
if (!config('addresses.geocoding.strict')) {
$googleMaps = $googleMaps->allowPartialMatches();
}

$latLng = $googleMaps->geocode($this->human_readable);

if ($latLng) {
$this->latitude = $latLng->lat;
$this->longitude = $latLng->long;
} else {
$this->latitude = null;
$this->longitude = null;
}
}

public function isGeocoded(): bool
Expand Down
5 changes: 5 additions & 0 deletions src/Objects/Location.php
Original file line number Diff line number Diff line change
Expand Up @@ -2,6 +2,7 @@

namespace DivineOmega\LaravelAddresses\Objects;

use Exception;
use DivineOmega\Distance\Point;
use DivineOmega\LaravelAddresses\Models\Address;

Expand All @@ -16,6 +17,10 @@ public function __construct(Address $address)
$address->geocode();
}

if (!$address->isGeocoded()) {
throw new Exception('Failed to geocode the Address to create a Location.');
}

$this->lat = $address->latitude;
$this->lng = $address->longitude;
}
Expand Down
7 changes: 6 additions & 1 deletion src/config/addresses.php
Original file line number Diff line number Diff line change
@@ -1,10 +1,15 @@
<?php

return [
'validation' => [
'uk-postcode' => true,
'country-code' => true,
],
'geocoding' => [
'enabled' => true,
'google-maps' => [
'api-key' => env('GEOCODING_GOOGLE_MAPS_API_KEY'),
]
],
'strict' => false,
]
];
Original file line number Diff line number Diff line change
@@ -0,0 +1,32 @@
<?php

use Illuminate\Database\Migrations\Migration;
use Illuminate\Database\Schema\Blueprint;
use Illuminate\Support\Facades\Schema;

class AddAddressableIndex extends Migration
{
/**
* Run the migrations.
*
* @return void
*/
public function up()
{
Schema::table('addresses', function (Blueprint $table) {
$table->index(['addressable_type', 'addressable_id']);
});
}

/**
* Reverse the migrations.
*
* @return void
*/
public function down()
{
Schema::table('addresses', function (Blueprint $table) {
$table->dropIndex(['addressable_type', 'addressable_id']);
});
}
}

0 comments on commit b5cdc0f

Please sign in to comment.