PrinceMinky's avatar

Get Longitude/Latitude from Address.

I have installed a package, toin0u/Geotools-laravel, from GitHub.

What I'm looking to do is have two fields on the register page one has "Country" and the other is "Hometown". They are stored in the database formatted like: "United Kingdom, Essex".

What I want to do is get the longitude and latitude via the address.

I watched an episode on here where Jeffrey did it, using Google Maps and Vue but I want it to all be done in the controller. With the package I've installed, is what I want possible?

0 likes
2 replies
martinbean's avatar
Level 80

@miiikkeyyyy I wouldn’t do any geocoding in a controller, as if the geocoding service takes a long time to load, is down etc, then you’re putting that on the user. Instead, I do it in a queued job, which can keep re-trying if geocoding isn’t successful for whatever reason.

In the past, I’ve had an interface that mandates two methods:

interface Geocodable
{
    public function getAddressString();
    public function setCoordinates($latitude, $longitude);
}

I then apply this to whatever model I want to be “geocodable”:

class Venue extends Model implements Geocodable
{
    public function getAddressString()
    {
        return sprintf('%s, %s', $this->hometown, $this->country);
    }

    public function setCoordinates($latitude, $longitude)
    {
        return $this->update(compact('latitude', 'longitude'));
    }
}

Then when a model is created, I’ll dispatch a job:

class VenueController extends Controller
{
    public function store(Request $request)
    {
        $venue = Venue::create($request->all());

        $this->dispatch(new GeocodeAddress($venue));

        // Set flash message and redirect
    }
}

The job itself looks like this:

class GeocodeAddress extends Job implements SelfHandling, ShouldQueue
{
    use InteractsWithQueue, SerializesModels;

    public $model;

    public function __construct(Geocodable $model)
    {
        $this->model = $model;
    }

    public function handle()
    {
        $result = Geocoder::geocode($this->model->getAddressString());

        $this->model->setCoordinates($result->getLatitude(), $result->getLongitude());
    }
}

As you can see, the Geocodable contract makes sure the methods are available in the job class.

You also probably want to use the https://github.com/geocoder-php/GeocoderLaravel package for actually geocoding address strings.

Reached's avatar

I just glanced over the documentation, and found this:

"Geotools is built atop Geocoder. It means it's possible to use the \Geocoder\Model\Address directly but it's also possible to use a string     or a simple array with its latitude and longitude."

Maybe this:

// from an \Geocoder\Model\Address instance within Airy ellipsoid
$coordinate = new Coordinate($geocoderResult, Ellipsoid::createFromName(Ellipsoid::AIRY));

Please or to participate in this conversation.