GeoSpatial integration on Laravel 5.2+ that supports MySQL and PostgreSQL.

Overview

Features

  • GeoSpatial integration on Laravel 5.2+:
    • Create geospatial columns using Schema and migrations
    • Save and retrieve geospatial attributes using directly OpenGeoConsortium Spatial Objects (this package depends from PHP-OGC)
    • Build spatial query directly with the laravel fluent query builder
    • Supported types: Point, MultiPoint, Linestring, MultiLinestring, Polygon, MultiPolygon, GeometryCollection
  • Supported drivers:
    • Postgres: Posgis extension Extensions (geometry types)
    • MySql: Extension for Spatial Data (geography types)

Thanks to https://github.com/njbarrett/laravel-postgis for its original work.

Installation & Configuration

  1. Install using composer
$ composer require elevenlab/laravel-geo
  1. Replace under the Service Providers section ('providers' array) in config/app.php this line
Illuminate\Database\DatabaseServiceProvider::class,

with this one:

ElevenLab\GeoLaravel\DatabaseServiceProvider::class
  1. If you need it, under the Alias section ('aliases' array) in config/app.php add this line:
'GeoModel'      => ElevenLab\GeoLaravel\Model::class,

Quick Documentation

Create table with spatial references

To add a geospatial field to your migration you can use these methods:

  • point, multipoint linestring, multilinestring, polygon, multipolygon, geometrycollection

Example (NB: the schema is over-semplified):

<?php
Schema::create('nations', function (Blueprint $table) {
    $table->increments('id');
    $table->string('name');
    $table->polygon('national_bounds');
    $table->point('capital');
    $table->multipolygon('regions_bounds');
    $table->multipoint('regions_capitals');
    $table->linestring('highway');
});

Add spatial attributes to a Model

In order to handle dinamically geospatial attributes during CRUD operations, you need to:

  • substitute the Eloquent Model abstract object with a custom Model
  • define which attribute belongs to which geospatial type, defining the $geometries attribute (you can find here the available types)
<?php namespace App;

use ElevenLab\GeoLaravel\Eloquent\Model as GeoModel;

class Country extends GeoModel
{
    protected $table = "countries";

    protected $geometries = [
        "polygons" =>   ['national_bounds'],
        "points" => ['capital'],
        "multipolygons" => ['regions_bounds'],
        "multipoints" => ['regions_capitals'],
        "linestrings" => ['highway']
    ];
}

Manipulate spatial attributes of a Model

<?php
use ElevenLab\GeoLaravel\DataTypes\Point as Point;
use ElevenLab\GeoLaravel\DataTypes\Linestring as Linestring;
use ElevenLab\GeoLaravel\DataTypes\Polygon as Polygon;

$rome = new Point(41.9102415,12.3959149);
$milan = new Point(45.4628328,9.1076927);
$naples = new Point(40.8540943,14.1765626);
$regions_capital = new MultiPoint([$rome, $milan, $naples, ....]);
$italy_bounds = new Polygon([new LineString(getPointArrayOfItalianBounds())]);
$lazio = new LineString(getPointArrayOfLazioBounds());
$campania = new LineString(getPointArrayOfCampaniaBounds());
$lombardia = new LineString(getPointArrayOfLombardiaBounds());
$molise = new LineString(getPointArrayOfMoliseBounds()); # raise MoliseNotFoundException
$regions_bounds = new MultiPolygon([$lazio, $campania, $lombardia, ....]);
$a1 = new LineString(getPointArrayOfA1());

$italy = Country::create([
    'name' => 'Italy',
    'capital' => $rome,
    'national_bounds' => $italy_bounds,
    'regions_bounds' => $regions_bounds,
    'regions_capitals' => $regions_capital,
    'highway' => $a1
]);

$italy = Country::whereName('Italy')->first();
echo get_class($italy->capital); // ElevenLab\PHPOGC\DataTypes\Point
echo get_class($italy->national_bounds); // ElevenLab\PHPOGC\DataTypes\Polygon
echo get_class($italy->regions_bounds); // ElevenLab\PHPOGC\DataTypes\Polygon
echo get_class($italy->regions_capitals); // ElevenLab\PHPOGC\DataTypes\MultiPoint
echo get_class($italy->highway); // ElevenLab\PHPOGC\DataTypes\LineString

Builds queries

There are two different groups of methods that are available, one to use the underlying database engine to perform spatial operations on existing objects, and another to build fluent queries and perform operations on database-resident data.

Given two OGCObjects, you can perform those operations:

  • intersection

  • difference

  • contains

  • intersects

  • touches

  • overlaps

  • centroid

  • distance

  • equals

Given an illuminate Query Builder object, you can use:

  • whereEquals

  • whereNotEquals

  • orWhereEquals

  • orWhereNotEquals

  • whereContains

  • whereNotContains

  • orWhereContains

  • orWhereNotContains

  • whereIntersects

  • whereNotIntersects

  • orWhereIntersects

  • orWhereNotIntersects

  • whereTouches

  • whereNotTouches

  • orWhereTouches

  • orWhereNotTouches

  • whereOverlaps

  • whereNotOverlaps

  • orWhereOverlaps

  • orWhereNotOverlaps

ToDo

  • improve documentation
    • add examples for "Build queries" section
    • add manual installation guide
  • add missing ST_functionsù
  • add unit tests
Comments
  • multipolygon attribute showing up with wrong characters

    multipolygon attribute showing up with wrong characters

    I'm having trouble getting a multipolygon field to show actual text from my database. Here is what I am doing.

    table column "radar_map" has the following data:

    MULTIPOLYGON(((-84.0330505 38.4686433,-83.71444700000001 38.2424946,-83.6334229 38.177751,-83.5606384 38.231708,-83.5345459 38.2435731,-83.5153198 38.2575931,-83.4933472 38.2683758,-83.5057068 38.285625,-83.46176149999999 38.3712706,-83.58055109999999 38.4089441,-83.62106319999999 38.5363501,-83.8929749 38.463267,-83.95202639999999 38.5213097,-84.0330505 38.4686433),(-84.2266846 38.8193811,-84.2129517 38.6093591,-84.21157839999999 38.5599788,-84.1333008 38.5513874,-84.1140747 38.5878935,-84.02618409999999 38.5793055,-83.8799286 38.7610441,-83.964386 38.785134,-84.03717039999999 38.7680042,-84.1209412 38.7819225,-84.20471190000001 38.7979786,-84.2266846 38.8193811),(-84.1333008 38.5513874,-84.1964722 38.5449433,-84.181366 38.4869197,-84.118818 38.4153888,-84.0509034 38.3868806,-83.9836121 38.4288493,-84.0330505 38.4686433,-83.95202639999999 38.5213097,-84.02618409999999 38.5793055,-84.1140747 38.5878935,-84.1333008 38.5513874),(-83.8799286 38.7610441,-84.02618409999999 38.5793055,-83.9588928 38.5304417,-83.8929749 38.463267,-83.62106319999999 38.5363501,-83.6375427 38.6458357,-83.66912840000001 38.6233082,-83.73229980000001 38.6447631,-83.76800540000001 38.6511983,-83.7927246 38.7048027,-83.84216309999999 38.7187333,-83.8572693 38.7562251,-83.8799286 38.7610441),(-83.6375427 38.6458357,-83.6203766 38.5223841,-83.58055109999999 38.4089441,-83.46176149999999 38.3712706,-83.4157562 38.3960297,-83.31962590000001 38.2904755,-83.25027470000001 38.3529649,-83.20358280000001 38.489607,-83.0415344 38.6340365,-83.0140686 38.7267689,-83.0332947 38.7176618,-83.05183409999999 38.6930132,-83.1088257 38.66782,-83.141098 38.6190164,-83.2104492 38.6125783,-83.2475281 38.6227717,-83.2901001 38.5916505,-83.31825259999999 38.600237,-83.3278656 38.616334,-83.3333588 38.6388636,-83.38897710000001 38.6592415,-83.46794130000001 38.6672839,-83.5249329 38.7005158,-83.57574459999999 38.6828298,-83.6238098 38.6758613,-83.6375427 38.6458357)))

    Here is my model...

    `
    namespace App;

    //use Illuminate\Database\Eloquent\Model;
    use ElevenLab\GeoLaravel\Eloquent\Model as GeoModel;
    
    
    class My_model extends GeoModel
    {
    
        protected $geometries = [ // docs at https://github.com/eleven-lab/laravel-geo
            "multipolygons" => ['radar_map']
        ];
    

    `

    here is my dump:

    dd($myModel->radar_map);

    and here is what i get:

    b""" \x00\x00\x00\x00\x01\x06\x00\x00\x00\x01\x00\x00\x00\x01\x03\x00\x00\x00\x05\x00\x00\x00\x0E\x00\x00\x00t'Ï\x7F\x1D\x02U└¿~´Ç³;[email protected]¯Þ\x7F╣ÝT└r:$\x10\n \[email protected]\x024\x00èÞT└hÛuï└\[email protected]Ô\x7FßÒT└\\x1Còø¿\[email protected]\x7F¡\x01\x006ÔT└╣WAg-\[email protected]═■Õ ·ÓT└o\x16褰 [email protected]»d"\x00ô▀T└Ï\x04b#Z"[email protected]Î\rÇ]ÓT└├§(\Å[email protected]\eÇì¦T└░{å╦à/[email protected]\t\n ═┐'ÕT└2▓┐[email protected]±/¦\x7F┐þT└iZ¢\x1Eº[email protected]çÚ1Ç&¨T└t(CUL;[email protected];#\x00¯³T└6K©F║[email protected]'Ï\x7F\x1D\x02U└¿~´Ç³;[email protected]\f\x00\x00\x00pÓ\x1F\x00é\x0EU└‗║┘zß[email protected]+╚*\x00í\rU└Å\x02ƒz [email protected]Å"!Çè\rU└\x07:ñb¡[email protected]÷!\x14\x00ê\x08U└ù6┴▄ô[email protected]° L\x07U└¸\x03\x1E\[email protected]@6K\x13\x00¡\x01U└Kr└«&[email protected]*¶\v└P°T└)(áõ[email protected]\x19«\x0EÇ©²T└$}ZE\[email protected]\x18§ \x02U└g\x18-÷[email protected]»(Ç¢\x07U└Î└V\t\[email protected]êµ­ \x19\rU└5¶¬)[email protected]Ó\x1F\x00é\x0EU└‗║┘zß[email protected]\v\x00\x00\x00÷!\x14\x00ê\x08U└ù6┴▄ô[email protected]»d"\x00ô\fU└PÍ╣│└[email protected]╬ª#Çø\vU└Üú}bS>[email protected]\vðÂÜ\x07U└÷Ť[email protected]ÉU\x00B\x03U└z:▓Mà[email protected]╦*Ǿ■T└═4½êõ[email protected]'Ï\x7F\x1D\x02U└¿~´Ç³;[email protected];#\x00¯³T└6K©F║[email protected]\x13\x00¡\x01U└Kr└«&[email protected]° L\x07U└¸\x03\x1E\[email protected]@÷!\x14\x00ê\x08U└ù6┴▄ô[email protected]\r\x00\x00\x00*¶\v└P°T└)(áõ[email protected]\x13\x00¡\x01U└Kr└«&[email protected]¼\x17Þ\x7F^²T└ó¸|âÕ[email protected]çÚ1Ç&¨T└t(CUL;[email protected]±/¦\x7F┐þT└iZ¢\x1Eº[email protected]ôÕ\x7F═ÞT└m\v६[email protected]╩┤ý ÊÛT└\x10*'É╚[email protected]⸷ ¦¯T└s\x15µÿç[email protected]▒\t\x1F\x00'±T└¹┌[email protected]\x05´§ ╗‗T└÷Pæ¨[email protected]\x19\x0F\x00µ§T└Þ\x05Ús [[email protected]Î\rǦ÷T└\tuý¹╦[email protected]*¶\v└P°T└)(áõ[email protected]\x1A\x00\x00\x00môÕ\x7F═ÞT└m\v६[email protected]\t\r\[email protected]┤þT└ª╣p{¦[email protected]\t\n ═┐'ÕT└2▓┐[email protected]\eÇì¦T└░{å╦à/[email protected]■åõ┐ø┌T└R▀Þ\x19▒[email protected]\x18¦0└tÈT└\x06e\x1AM.%[email protected]\n ß,Ç\x04ðT└f\x11/¶[email protected]═\x01'Ç\x07═T└Cr2q½>[email protected]µ\x7F¿┬T└3³º\e([email protected]ó9³\x7Fµ└T└²ƒh├\x06][email protected]Þ\x17Ç!┬T└TKäW▄[[email protected]\x14¨?Q├T└!┘\x12¿┤[email protected]ÀØ\x11\x00¸ãT└»╬1 {[email protected]³ßþ┐\x07╔T└\x05ÏýÝ;[email protected]\n ÌÙ w═T└í^:¸[email protected]Ëò\x19ÇΤT└Û/¬¹Â[email protected]?ä\x02\x00æÊT└¥\x14\x1E4╗[email protected]|7'@^ÈT└▒lµÉÈ[email protected]­^ ┐¹ÈT└┘┤R\x08õ[email protected]]§%└UıT└kMNHã[email protected]&┘4\x00ÕÏT└?Uà\[email protected]¿³\x10└‗¦T└▄Ê\x0FÅ[email protected]\vå)ÇÿßT└g¬qǬ[email protected]÷Ó ÏõT└¹¦à¸[email protected]({­\x7FýþT└þ\x10éƒé[email protected]ôÕ\x7F═ÞT└m\v६[email protected] """

    I've even tried various ways to override the attribute in the model but no luck.

    Any help would be super appreciated!

    opened by chuckienorton 5
  • dropColumn not working on rollback

    dropColumn not working on rollback

    I'm getting an error when running "php artisan migrate:rollback" Here is my code:

    Schema::table("mytable", function(Blueprint $table) { $table->multipolygon("radar_map")->after("radar_miles")->nullable()->comment("Overrides radar_radius_miles with a multipolygon."); });

    public function down() { Schema::table("mytable", function(Blueprint $table) { $table->dropColumn("radar_map"); }); }

    and the error... [Doctrine\DBAL\DBALException] Unknown database type multipolygon requested, Doctrine\DBAL\Platforms\MySQL57Platform may not support it.

    I also tried a DB::RAW statement and got the same response.

    DB::raw('ALTER TABLE mytable DROP radar_map;');

    Any ideas how to do this would be appreciated!

    bug 
    opened by chuckienorton 4
  • Fix typo ElevenLab\GeoLaravel\Eloquent\Model

    Fix typo ElevenLab\GeoLaravel\Eloquent\Model

    • MULTIPOINTS geotype is referenced to ElevenLab\PHPOGC\DataTypes\MultiPoints (with s) instead of ElevenLab\PHPOGC\DataTypes\MultiPoint
    • Use PostGIS GEOMETRY column type instead of GEOGRAPHY
    opened by sembrex 0
  • GeometryCollection operations (+ added fromArray fn)

    GeometryCollection operations (+ added fromArray fn)

    I'm trying to implement the fromArray functionality for GeometryCollection, but with this function

    public static function fromArray(array $items) {
        $parsed = array_map(function($p){
            if( !is_array($p) or sizeof($p) != 2)
                throw new GeoSpatialException('Error: array of array containing lat, lon expected.');
    
            if ($p['type'] == 'POLYGON') {
                $points = array_map(function ($p) {
                    if( !is_array($p) or sizeof($p) != 2)
                        throw new GeoSpatialException('Error: array of array containing lat, lon expected.');
    
                    return new Point($p[0], $p[1]);
                }, $p['value'][0]);
            }
    
            return new Polygon([new LineString($points)]);
        }, $items);
    
        return new static(new GeometryCollection([$parsed]));
    }```
    
    I'm getting this error:
    
    `ElevenLab\PHPOGC\Exceptions\GeoSpatialException with message 'A GeometryCollection must be constructed with an array of OGCObject objects'`
    
    It works fine with this `return new static($parsed));` however, I every whereX query fails, intersection, touches, etc.
    
    I have a few contribs for this library in the pipeline, hoping to gain a deeper understanding here so I can push forward.
    
    Cheers!
    opened by iredmedia 0
  • Call to undefined methodfromRawToWKB()

    Call to undefined methodfromRawToWKB()

    Hi i have problem,

    Call to undefined method Phaza\LaravelPostgis\PostgisConnection::fromRawToWKB()

    my data is: 0101000020CF7F00000000000004131A410000000062865D41

    opened by siturra 0
  • Drop explicit call to DB facade that may not be available

    Drop explicit call to DB facade that may not be available

    Hello!

    Thanks for your work on this package!

    This PR drops references to the DB facade. I ran into an issue with this on a Lumen project that doesn't use Facades where there was a "Class 'DB' not found" exception thrown. I noticed that the methods being called are actually on the Connection, so I opted to use the instance of the Connection that the model has access to anyway, rather than calling the DB facade. :smile:

    Thanks!

    opened by trea 2
Owner
Eleven
Software development agency, where everything starts!
Eleven
PHP extension for geospatial rendering with Mapnik

PHP7 Mapnik Introduction This project is an extension for PHP 7 that enables geospatial rendering with Mapnik. Create tile generation scripts, dynamic

Garrett Johnson 20 Sep 17, 2022
PHP Extension to handle common geospatial functions.

geospatial - PHP Geospatial Extension PHP Extension to handle common geospatial functions. The extension currently has implementations of the Haversin

PHP Geospatial, putting the Elephpant on your globe 54 Sep 9, 2022
A Laravel package to get the user's country using the ip.

Laravel IP Service Tries to guess the country code of the client, using his IP. Installation Download and import the ip database from ip2nation.com Us

Dimitris Savvopoulos 118 Apr 12, 2022
A Laravel package that uses geoPlugin web service to fetch information from an IP.

LarageoPlugin (Laravel 4 Package) A Laravel package that uses geoPlugin web service to fetch information from an IP. It will store in cache the IP inf

Ricardo Fuhrmann 9 Aug 18, 2022
Geo-related tools PHP 5.4+ library built atop Geocoder and React libraries

Geotools Geotools is a PHP geo-related library, built atop Geocoder and React libraries. Features Batch geocode & reverse geocoding request(s) in seri

The League of Extraordinary Packages 1.3k Sep 19, 2022
PHP library to easily get static image from French Cadastral Government map with markers and lines.

PHP French Cadastral Map Static API PHP library to easily get static image from French Cadastral Government map with markers and lines. Map source : c

Franck Alary 3 May 24, 2022
PHP library to easily get static image from OpenStreetMap (OSM) with markers and lines.

PHP OpenStreetMap Static API PHP library to easily get static image from OpenStreetMap with markers and lines. ✨ Supporting ⭐ Star this repository to

Franck Alary 29 Sep 19, 2022
Use: [i] to share item and name in hand, [coor] to share you current coordinates

General Now you can share your Coordinates and Item with Prefix Example if you type [i] in message, later it will be automatically replaced into the n

ItsRealNise 7 Oct 15, 2021
Generate and display maps without external services or compromising on privacy.

Generate and display maps without external services or compromising on privacy.

null 142 Sep 17, 2022
Official PHP library for IPinfo (IP geolocation and other types of IP data)

This is the official PHP client library for the IPinfo.io IP address API, allowing you to lookup your own IP address,

IPinfo 154 Sep 19, 2022
Laravel package to work with geospatial data types and functions.

Laravel Spatial Laravel package to work with geospatial data types and functions. For now it supports only MySql Spatial Data Types and Functions. Sup

Tarfin 46 Jul 17, 2022
Free database of geographic place names and corresponding geospatial data

FreeGeoDB Free database of geographic place names and corresponding geospatial data Entities airports cities countries (admin-0) lakes ports railroads

delight.im 1.6k Aug 28, 2022
PHP extension for geospatial rendering with Mapnik

PHP7 Mapnik Introduction This project is an extension for PHP 7 that enables geospatial rendering with Mapnik. Create tile generation scripts, dynamic

Garrett Johnson 20 Sep 17, 2022
PHP Extension to handle common geospatial functions.

geospatial - PHP Geospatial Extension PHP Extension to handle common geospatial functions. The extension currently has implementations of the Haversin

PHP Geospatial, putting the Elephpant on your globe 54 Sep 9, 2022
phpMyFAQ - Open Source FAQ web application for PHP and MySQL, PostgreSQL and other databases

phpMyFAQ 3.1 What is phpMyFAQ? phpMyFAQ is a multilingual, completely database-driven FAQ-system. It supports various databases to store all data, PHP

Thorsten Rinne 537 Sep 23, 2022
Bolt is a simple CMS written in PHP. It is based on Silex and Symfony components, uses Twig and either SQLite, MySQL or PostgreSQL.

⚠️ Note - Not the latest version This is the repository for Bolt 3. Please know that Bolt 5 has been released. If you are starting a new project, plea

Bolt 4.1k Sep 23, 2022
Independent query builders for MySQL, PostgreSQL, SQLite, and Microsoft SQL Server.

Aura.SqlQuery Provides query builders for MySQL, Postgres, SQLite, and Microsoft SQL Server. These builders are independent of any particular database

Aura for PHP 419 Sep 28, 2022
PHP Kafka client is used in PHP-FPM and Swoole. PHP Kafka client supports 50 APIs, which might be one that supports the most message types ever.

longlang/phpkafka Introduction English | 简体中文 PHP Kafka client is used in PHP-FPM and Swoole. The communication protocol is based on the JSON file in

Swoole Project 223 Sep 23, 2022