MySQL Spatial Data Extension integration with Laravel.

Overview

Laravel MySQL Spatial extension

Build Status Code Climate Code Climate Packagist Packagist StyleCI license

Laravel package to easily work with MySQL Spatial Data Types and MySQL Spatial Functions.

Please check the documentation for your MySQL version. MySQL's Extension for Spatial Data was added in MySQL 5.5 but many Spatial Functions were changed in 5.6 and 5.7.

Versions

  • 1.x.x: MySQL 5.6 (also supports MySQL 5.5 but not all spatial analysis functions)
  • 2.x.x: MySQL 5.7 and 8.0 (Laravel version < 8.0)
  • 3.x.x: MySQL 8.0 with SRID support (Laravel version < 8.0)
  • 4.x.x: MySQL 8.0 with SRID support (Laravel 8+) [Current branch]
  • 5.x.x: MySQL 5.7 and 8.0 (Laravel 8+)

This package also works with MariaDB. Please refer to the MySQL/MariaDB Spatial Support Matrix for compatibility.

Installation

Add the package using composer:

$ composer require grimzy/laravel-mysql-spatial:^4.0

# or for Laravel version < 8.0
$ composer require grimzy/laravel-mysql-spatial:^3.0

For MySQL 5.7:

$ composer require grimzy/laravel-mysql-spatial:^2.0

For MySQL 5.6 and 5.5:

$ composer require grimzy/laravel-mysql-spatial:^1.0

For Laravel versions before 5.5 or if not using auto-discovery, register the service provider in config/app.php:

'providers' => [
  /*
   * Package Service Providers...
   */
  Grimzy\LaravelMysqlSpatial\SpatialServiceProvider::class,
],

Quickstart

Create a migration

From the command line:

php artisan make:migration create_places_table

Then edit the migration you just created by adding at least one spatial data field. For Laravel versions prior to 5.5, you can use the Blueprint provided by this package (Grimzy\LaravelMysqlSpatial\Schema\Blueprint):

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

// For Laravel < 5.5
// use Grimzy\LaravelMysqlSpatial\Schema\Blueprint;

class CreatePlacesTable extends Migration {

    /**
     * Run the migrations.
     *
     * @return void
     */
    public function up()
    {
        Schema::create('places', function(Blueprint $table)
        {
            $table->increments('id');
            $table->string('name')->unique();
            // Add a Point spatial data field named location
            $table->point('location')->nullable();
            // Add a Polygon spatial data field named area
            $table->polygon('area')->nullable();
            $table->timestamps();
        });
  
        // Or create the spatial fields with an SRID (e.g. 4326 WGS84 spheroid)
  
        // Schema::create('places', function(Blueprint $table)
        // {
        //     $table->increments('id');
        //     $table->string('name')->unique();
        //     // Add a Point spatial data field named location with SRID 4326
        //     $table->point('location', 4326)->nullable();
        //     // Add a Polygon spatial data field named area with SRID 4326
        //     $table->polygon('area', 4326)->nullable();
        //     $table->timestamps();
        // });
    }

    /**
     * Reverse the migrations.
     *
     * @return void
     */
    public function down()
    {
        Schema::drop('places');
    }
}

Run the migration:

php artisan migrate

Create a model

From the command line:

php artisan make:model Place

Then edit the model you just created. It must use the SpatialTrait and define an array called $spatialFields with the name of the MySQL Spatial Data field(s) created in the migration:

namespace App;

use Illuminate\Database\Eloquent\Model;
use Grimzy\LaravelMysqlSpatial\Eloquent\SpatialTrait;

/**
 * @property \Grimzy\LaravelMysqlSpatial\Types\Point   $location
 * @property \Grimzy\LaravelMysqlSpatial\Types\Polygon $area
 */
class Place extends Model
{
    use SpatialTrait;

    protected $fillable = [
        'name'
    ];

    protected $spatialFields = [
        'location',
        'area'
    ];
}

Saving a model

use Grimzy\LaravelMysqlSpatial\Types\Point;
use Grimzy\LaravelMysqlSpatial\Types\Polygon;
use Grimzy\LaravelMysqlSpatial\Types\LineString;

$place1 = new Place();
$place1->name = 'Empire State Building';

// saving a point
$place1->location = new Point(40.7484404, -73.9878441);	// (lat, lng)
$place1->save();

// saving a polygon
$place1->area = new Polygon([new LineString([
    new Point(40.74894149554006, -73.98615270853043),
    new Point(40.74848633046773, -73.98648262023926),
    new Point(40.747925497790725, -73.9851602911949),
    new Point(40.74837050671544, -73.98482501506805),
    new Point(40.74894149554006, -73.98615270853043)
])]);
$place1->save();

Or if your database fields were created with a specific SRID:

use Grimzy\LaravelMysqlSpatial\Types\Point;
use Grimzy\LaravelMysqlSpatial\Types\Polygon;
use Grimzy\LaravelMysqlSpatial\Types\LineString;

$place1 = new Place();
$place1->name = 'Empire State Building';

// saving a point with SRID 4326 (WGS84 spheroid)
$place1->location = new Point(40.7484404, -73.9878441, 4326);	// (lat, lng, srid)
$place1->save();

// saving a polygon with SRID 4326 (WGS84 spheroid)
$place1->area = new Polygon([new LineString([
    new Point(40.74894149554006, -73.98615270853043),
    new Point(40.74848633046773, -73.98648262023926),
    new Point(40.747925497790725, -73.9851602911949),
    new Point(40.74837050671544, -73.98482501506805),
    new Point(40.74894149554006, -73.98615270853043)
])], 4326);
$place1->save();

Note: When saving collection Geometries (LineString, Polygon, MultiPoint, MultiLineString, and GeometryCollection), only the top-most geometry should have an SRID set in the constructor.

In the example above, when creating a new Polygon(), we only set the SRID on the Polygon and use the default for the LineString and the Point objects.

Retrieving a model

$place2 = Place::first();
$lat = $place2->location->getLat();	// 40.7484404
$lng = $place2->location->getLng();	// -73.9878441

Geometry classes

Available Geometry classes

Grimzy\LaravelMysqlSpatial\Types OpenGIS Class
Point($lat, $lng, $srid = 0) Point
MultiPoint(Point[], $srid = 0) MultiPoint
LineString(Point[], $srid = 0) LineString
MultiLineString(LineString[], $srid = 0) MultiLineString
Polygon(LineString[], $srid = 0) (exterior and interior boundaries) Polygon
MultiPolygon(Polygon[], $srid = 0) MultiPolygon
GeometryCollection(Geometry[], $srid = 0) GeometryCollection

Check out the Class diagram.

Using Geometry classes

In order for your Eloquent Model to handle the Geometry classes, it must use the Grimzy\LaravelMysqlSpatial\Eloquent\SpatialTrait trait and define a protected property $spatialFields as an array of MySQL Spatial Data Type column names (example in Quickstart).

IteratorAggregate and ArrayAccess

The collection Geometries (LineString, Polygon, MultiPoint, MultiLineString, and GeometryCollection) implement IteratorAggregate and ArrayAccess; making it easy to perform Iterator and Array operations. For example:

$polygon = $multipolygon[10];	// ArrayAccess

// IteratorAggregate
for($polygon as $i => $linestring) {
  echo (string) $linestring;
}

Helpers

From/To Well Known Text (WKT)
// fromWKT($wkt, $srid = 0)
$point = Point::fromWKT('POINT(2 1)');
$point->toWKT();	// POINT(2 1)

$polygon = Polygon::fromWKT('POLYGON((0 0,4 0,4 4,0 4,0 0),(1 1, 2 1, 2 2, 1 2,1 1))');
$polygon->toWKT();	// POLYGON((0 0,4 0,4 4,0 4,0 0),(1 1, 2 1, 2 2, 1 2,1 1))
From/To String
// fromString($wkt, $srid = 0)
$point = new Point(1, 2);	// lat, lng
(string)$point			// lng, lat: 2 1

$polygon = Polygon::fromString('(0 0,4 0,4 4,0 4,0 0),(1 1, 2 1, 2 2, 1 2,1 1)');
(string)$polygon;	// (0 0,4 0,4 4,0 4,0 0),(1 1, 2 1, 2 2, 1 2,1 1)
From/To JSON (GeoJSON)

The Geometry classes implement JsonSerializable and Illuminate\Contracts\Support\Jsonable to help serialize into GeoJSON:

$point = new Point(40.7484404, -73.9878441);

json_encode($point); // or $point->toJson();

// {
//   "type": "Feature",
//   "properties": {},
//   "geometry": {
//     "type": "Point",
//     "coordinates": [
//       -73.9878441,
//       40.7484404
//     ]
//   }
// }

To deserialize a GeoJSON string into a Geometry class, you can use Geometry::fromJson($json_string) :

$location = Geometry::fromJson('{"type":"Point","coordinates":[3.4,1.2]}');
$location instanceof Point::class;  // true
$location->getLat();  // 1.2
$location->getLng()); // 3.4

Scopes: Spatial analysis functions

Spatial analysis functions are implemented using Eloquent Local Scopes.

Available scopes:

  • distance($geometryColumn, $geometry, $distance)
  • distanceExcludingSelf($geometryColumn, $geometry, $distance)
  • distanceSphere($geometryColumn, $geometry, $distance)
  • distanceSphereExcludingSelf($geometryColumn, $geometry, $distance)
  • comparison($geometryColumn, $geometry, $relationship)
  • within($geometryColumn, $polygon)
  • crosses($geometryColumn, $geometry)
  • contains($geometryColumn, $geometry)
  • disjoint($geometryColumn, $geometry)
  • equals($geometryColumn, $geometry)
  • intersects($geometryColumn, $geometry)
  • overlaps($geometryColumn, $geometry)
  • doesTouch($geometryColumn, $geometry)
  • orderBySpatial($geometryColumn, $geometry, $orderFunction, $direction = 'asc')
  • orderByDistance($geometryColumn, $geometry, $direction = 'asc')
  • orderByDistanceSphere($geometryColumn, $geometry, $direction = 'asc')

Note that behavior and availability of MySQL spatial analysis functions differs in each MySQL version (cf. documentation).

Migrations

For Laravel versions prior to 5.5, you can use the Blueprint provided with this package: Grimzy\LaravelMysqlSpatial\Schema\Blueprint.

use Illuminate\Database\Migrations\Migration;
use Grimzy\LaravelMysqlSpatial\Schema\Blueprint;

class CreatePlacesTable extends Migration {
    // ...
}

Columns

Available MySQL Spatial Types migration blueprints:

  • $table->geometry(string $column_name, int $srid = 0)
  • $table->point(string $column_name, int $srid = 0)
  • $table->lineString(string $column_name, int $srid = 0)
  • $table->polygon(string $column_name, int $srid = 0)
  • $table->multiPoint(string $column_name, int $srid = 0)
  • $table->multiLineString(string $column_name, int $srid = 0)
  • $table->multiPolygon(string $column_name, int $srid = 0)
  • $table->geometryCollection(string $column_name, int $srid = 0)

Spatial indexes

You can add or drop spatial indexes in your migrations with the spatialIndex and dropSpatialIndex blueprints.

  • $table->spatialIndex('column_name')
  • $table->dropSpatialIndex(['column_name']) or $table->dropSpatialIndex('index_name')

Note about spatial indexes from the MySQL documentation:

For MyISAM and (as of MySQL 5.7.5) InnoDB tables, MySQL can create spatial indexes using syntax similar to that for creating regular indexes, but using the SPATIAL keyword. Columns in spatial indexes must be declared NOT NULL.

Also please read this important note regarding Index Lengths in the Laravel 5.6 documentation.

For example, as a follow up to the Quickstart; from the command line, generate a new migration:

php artisan make:migration update_places_table

Then edit the migration file that you just created:

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

class UpdatePlacesTable extends Migration
{
    /**
     * Run the migrations.
     *
     * @return void
     */
    public function up()
    {
        // MySQL < 5.7.5: table has to be MyISAM
        // \DB::statement('ALTER TABLE places ENGINE = MyISAM');

        Schema::table('places', function (Blueprint $table) {
            // Make sure point is not nullable
            $table->point('location')->change();
          
            // Add a spatial index on the location field
            $table->spatialIndex('location');
        });
    }

    /**
     * Reverse the migrations.
     *
     * @return void
     */
    public function down()
    {
        Schema::table('places', function (Blueprint $table) {
            $table->dropSpatialIndex(['location']); // either an array of column names or the index name
        });

        // \DB::statement('ALTER TABLE places ENGINE = InnoDB');

        Schema::table('places', function (Blueprint $table) {
            $table->point('location')->nullable()->change();
        });
    }
}

Tests

$ composer test
# or 
$ composer test:unit
$ composer test:integration

Integration tests require a running MySQL database. If you have Docker installed, you can start easily start one:

$ make start_db		# starts MySQL 8.0
# or
$ make start_db V=5.7	# starts MySQL 5.7

Contributing

Recommendations and pull request are most welcome! Pull requests with tests are the best! There are still a lot of MySQL spatial functions to implement or creative ways to use spatial functions.

Credits

Originally inspired from njbarrett's Laravel postgis package.

Comments
  • Select polygon from DB

    Select polygon from DB

    I have an issue to pass the polygon data from DB to Client. I save the polygon like this:

    // Save item
    $item = new Item($data);
    ...
    $item->polygon = $this->buildPolygonFromArray($data['polygon']);
    $item->save();
    
    // Build polygon from array
    use Grimzy\LaravelMysqlSpatial\Types\LineString;
    use Grimzy\LaravelMysqlSpatial\Types\Point;
    use Grimzy\LaravelMysqlSpatial\Types\Polygon;
    
    private function buildPolygonFromArray($polygon) {
            $points = $polygon['coordinates'][0];
            $arrayOfPoints = [];
            foreach ($points as $point) {
                $arrayOfPoints[] = new Point($point[0], $point[1]);
            }
            $lineString = new LineString($arrayOfPoints);
            return new Polygon([$lineString]);
        }
    

    Now the polygon is been selected automatically by laravel and passed to the client BUT the problem is that the latitude and longitude are been switched in positions. I send this array with lat&long points:

    'polygon' =>
                    [
                        'coordinates' =>
                            [
                                0 => [
                                    [34.783342, 32.075312],
                                    [34.782876, 32.075323],
                                    [34.782862, 32.074953],
                                    [34.783407, 32.07494],
                                    [34.783342, 32.075312],
                                ],
                            ]
                    ]
    

    On DB it's been saved on the opposite way (long&lat) because of the Point()->toPair() function but it is totally OK. The problem is with the select and passing to client.

    The response I get in the network is like this: {"type":"Polygon","coordinates":[[[32.075312,34.783342],[32.075323,34.782876],[32.074953,34.782862],[32.07494,34.783407],[32.075312,34.783342]]]}

    When I'm going over the array the points are in Long&Lat format which is not good, I need it in the same format I create the polygon: [Lat&Long]

    I thought about working with public function getPolygonAttribute($value) on the laravel side but still I need help here.

    Thank you in advance, Lior.

    question 
    opened by llioor 13
  • Numeric value out of range when inserting

    Numeric value out of range when inserting

    I get this error message when I do a simple insert to a Point field:

    SQLSTATE[22003]: Numeric value out of range: 1416 Cannot get geometry object from data you send to the GEOMETRY field (SQL: insert into `addresses` (`type`, `address_line_1`, `address_line_2`, `city`, `postal_code`, `country`, `user_uuid`, `uuid`, `location`, `updated_at`, `created_at`) values (billing, Drottninggatan 11, , Stockholm, 111 51, SE, ad120958-31b9-44da-92a8-e990c20eac42, 5bfa2e46-8fa5-4fbc-b818-0066adc858b8, 59.3315493 18.0637367, 2019-03-07 17:07:33, 2019-03-07 17:07:33))
    

    The only solutions I can find is to add SpatialTrait and $spatialFields, but I already have them. This the relevant parts of the model:

    <?php 
    
    class Address extends Model
    {
        use SpatialTrait;
    
        protected $spatialFields = ['location'];
    
        public static function boot()
        {
            parent::boot();
    
            self::creating(function (Address $address) {
    
                if (
                    empty($address->attributes['location']) &&
                    $address->isComplete()
                ) {
                    $geocoded = app('geocoder')->geocodeAddress($address);
                    $address->attributes['location'] = new Point($geocoded['latitude'], $geocoded['longitude']);
                }
            });
        }
    
        public function isComplete()
        {
            return isset($this->type, $this->address_line_1, $this->city, $this->postal_code, $this->country);
        }
    }
    
    

    I have double and triple checked the code, but I can't find anything wrong. Any ideas?

    bug 
    opened by pelmered 10
  • compatibility issue

    compatibility issue

    Hi,

    refere to laravel\framework commit of Add support for defining a Spatial reference system for a Point column. (code: ddc4e05fc03a8f55a56be2afdce48ba891879d65), they add srid to declearation of point method.

    Due to what I mentioned above, it needs to make point method your Blueprint compatible.

    check following error:

    Declaration of Grimzy\LaravelMysqlSpatial\Schema\Blueprint::point($column) should be compatible with Illuminate\Database\Schema\Blueprint::point($column, $srid = NULL)
    
    bug 
    opened by enourinick 9
  • Tip to get filtered Places by KM

    Tip to get filtered Places by KM

    How I can filter items by KM

    E.G: get items at distance 3KM radius from an origin point

    My code so far

    `

        $origin = Place::first();
    
        $lat = $origin->location->getLat();
    
        $lng = $origin->location->getLng();
    
        $point = new Point($lat, $lng);
    
        $distance = 3;
    
        $places = Place::distanceExcludingSelf('location', $point, $distance)->get();
    
        return response($places);
    

    `

    But not works well way now

    opened by fredroo 8
  • grabbing distance value when querying/sorting

    grabbing distance value when querying/sorting

    i'd like to get the distance value of each result as they are returned using the distance and/or distanceSphere scopes.

    is this possible to do at all? is it easy to add?

    question 
    opened by acidjazz 8
  • Unable to run within when different SRID generated

    Unable to run within when different SRID generated

    I've table like this:

    CREATE TABLE `jovan_test` (
      `id` int(10) unsigned NOT NULL AUTO_INCREMENT,
      `properties__name` varchar(255) COLLATE utf8_unicode_ci GENERATED ALWAYS AS (json_unquote(json_extract(`__docs`,'$.properties.name'))) VIRTUAL,
      `properties__age` int(11) GENERATED ALWAYS AS (json_unquote(json_extract(`__docs`,'$.properties.age'))) VIRTUAL,
      `properties__height` int(11) GENERATED ALWAYS AS (json_unquote(json_extract(`__docs`,'$.properties.height'))) VIRTUAL,
      `properties__address__city` varchar(255) COLLATE utf8_unicode_ci GENERATED ALWAYS AS (json_unquote(json_extract(`__docs`,'$.properties.address.city'))) VIRTUAL,
      `properties__address__zip_code` varchar(255) COLLATE utf8_unicode_ci GENERATED ALWAYS AS (json_unquote(json_extract(`__docs`,'$.properties.address.zip_code'))) VIRTUAL,
      `properties__address__state` varchar(255) COLLATE utf8_unicode_ci GENERATED ALWAYS AS (json_unquote(json_extract(`__docs`,'$.properties.address.state'))) VIRTUAL,
      `properties__address__country` varchar(255) COLLATE utf8_unicode_ci GENERATED ALWAYS AS (json_unquote(json_extract(`__docs`,'$.properties.address.country'))) VIRTUAL,
      `properties__address__home_coordinate` point GENERATED ALWAYS AS (st_geomfromgeojson(json_unquote(json_extract(`__docs`,'$.properties.address.home_coordinate')))) VIRTUAL,
      `properties__address__routes` geometry GENERATED ALWAYS AS (st_geomfromgeojson(json_unquote(json_extract(`__docs`,'$.properties.address.routes')))) VIRTUAL,
      `__docs` json NOT NULL,
      `created_at` timestamp NULL DEFAULT NULL,
      `updated_at` timestamp NULL DEFAULT NULL,
      PRIMARY KEY (`id`),
      KEY `jovan_test_properties__name_index` (`properties__name`),
      KEY `jovan_test_properties__age_index` (`properties__age`),
      KEY `jovan_test_properties__height_index` (`properties__height`),
      KEY `jovan_test_properties__address__city_index` (`properties__address__city`),
      KEY `jovan_test_properties__address__zip_code_index` (`properties__address__zip_code`),
      KEY `jovan_test_properties__address__state_index` (`properties__address__state`),
      KEY `jovan_test_properties__address__country_index` (`properties__address__country`)
    ) ENGINE=InnoDB AUTO_INCREMENT=2 DEFAULT CHARSET=utf8 COLLATE=utf8_unicode_ci;
    

    Insert new value like this:

    insert into jovan_test set __docs = '{"properties": {"age": 29, "name": "Rahmat Awaludin", "height": 160, "address": {"city": "Bandung", "state": "Jawa Barat", "routes": {"type": "LineString", "coordinates": [[102, 0], [103, 1], [104, 0], [105, 1]]}, "country": "Indonesia", "zip_code": "43193", "home_coordinate": {"type": "Point", "coordinates": [30, 10]}}}}'
    

    With resulting like this:

    mysql root@localhost:intelligence> select id, st_astext(properties__address__home_coordinate) from jovan_test;
    +----+-------------------------------------------------+
    | id | st_astext(properties__address__home_coordinate) |
    +----+-------------------------------------------------+
    | 2  | POINT(30 10)                                    |
    +----+-------------------------------------------------+
    

    The within query generated query like this:

    select * from `jovan_test` where st_within(`properties__address__home_coordinate`, ST_GeomFromText("POLYGON((40 -10,-10 -10,-10 40,40 40,40 -10))"))
    

    It silently error on mysql (I don't get error message in laravel), the message like this:

    Binary geometry function st_within given two geometries of different srids: 4326 and 0, which should have been identical.
    

    This because ST_GeomFromGeoJson generate SRID 4326 by default see here if none provided.

    The srid argument, if given, must be a 32-bit unsigned integer. If not given, the geometry return value has an SRID of 4326.

    While ST_GeomFromText generate SRID 0 by default if not provided see here.

    This can be solved by using SRID to 0 on first ST_GeomFromGeoJson call. That is possible with this library.

    But, I believe allowing set SRID on scopeWithin will work best. So the resulting query would be

    select * from `jovan_test` where st_within(`properties__address__home_coordinate`, ST_GeomFromText("POLYGON((40 -10,-10 -10,-10 40,40 40,40 -10))",4326))
    

    This sinergy with allowing SRID on creating column as you alredy done.

    What do you think? I can prepare a PR if you want.

    enhancement 
    opened by rawaludin 7
  • SQL Injection

    SQL Injection

    Clicking through the source code has me worried. It looks like this package facilitates SQL Injections.

    For example the scopeDistance function

    public function scopeDistance($query, $geometryColumn, $geometry, $distance)
        {
            $query->whereRaw("st_distance(`{$geometryColumn}`, ST_GeomFromText('{$geometry->toWkt()}')) <= {$distance}");
    
            return $query;
        }
    

    The user data is just executed raw, no bindings, no escaping. Doing a simple test below shows it allows for SQL Injection.

    >>> Address::distance('location', new \Grimzy\LaravelMysqlSpatial\Types\Point(51.905737, 4.430866), "'' OR 1=1")->toSql()
    => "select * from `addresses` where st_distance(`location`, ST_GeomFromText('POINT(4.430866 51.905737)')) <= '' OR 1=1"
    
    enhancement 
    opened by Dylan-DutchAndBold 7
  • How is this supposed to work?

    How is this supposed to work?

    Further to #39, I've been trying to use a point field via latitude and longitude virtual properties, but I can't make it behave usefully at all.

    In my model, I've declared some fillable & location properties, much as in the provided example code:

    protected $fillable = [
        'name',
        'address',
        'type',
        'longitude',
        'latitude',
    ];
    
    protected $spatialFields = [
        'location',
    ];
    

    location is defined in the database as a Laravel point type. longitude and latitude do not exist in the database, so I implemented them with accessors and mutators in the model like this:

    public function getLongitudeAttribute()
    {
        return $this->location->getLng();
    }
    
    public function getLatitudeAttribute()
    {
        return $this->location->getLat();
    }
    
    public function setLongitudeAttribute($longitude)
    {
        $this->location->setLng($longitude);
    }
    
    public function setLatitudeAttribute($latitude)
    {
        $this->location->setLat($latitude);
    }
    

    Then I send a PUT request to update a record containing a param string:

    name=Smurf+city&latitude=21.21&longitude=150.15&type=account&address=123+main+st
    

    However, this fails in the first mutator it runs:

    "message": "Undefined index: location",
    "exception": "ErrorException",
    "file": "/Users/marcus/Sites/app/Location.php",
    "line": 65,
    

    If I try to access location as a property in the mutator with $this->location->setLat($latitude);, I get an error because location is null (even though it's not allowed to be declared as nullable in the DB):

    "message": "Call to a member function setLat() on null",
    "exception": "Symfony\\Component\\Debug\\Exception\\FatalThrowableError",
    "file": "/Users/marcus/Sites/app/Location.php",
    "line": 65,
    

    What's even more confusing is that I get results back in a format that doesn't reflect my settings - I don't understand why this includes a location property that doesn't appear in the fillable array, but not the latitude and longitude values that do:

    {
        "id": 1,
        "created_at": "2018-03-16 16:39:47",
        "updated_at": "2018-03-16 16:39:49",
        "type": "account",
        "name": "Bernier Group",
        "address": "68914 Streich Springs Apt. 419\nVenabury, WI 39979-3229",
        "location": {
            "type": "Point",
            "coordinates": [
                -0.118092,
                51.509865
            ]
        }
    },
    

    This may be a broader Laravel question than something specific to this extension, but I don't know enough about either to tell. How should I be doing this?

    opened by Synchro 7
  • Composer dependency problem with Laravel 8

    Composer dependency problem with Laravel 8

    Please update the composer dependencies to allow it to work with Laravel 8 and illuminate/database 8.

    Problem 1 - Conclusion: remove grimzy/laravel-mysql-spatial 3.0.0 - Conclusion: don't install grimzy/laravel-mysql-spatial 3.0.0 - Conclusion: don't install laravel/framework v8.0.3 - Conclusion: don't install laravel/framework v8.0.2 - Conclusion: don't install laravel/framework v8.0.1 - Installation request for grimzy/laravel-mysql-spatial ^3.0 -> satisfiable by grimzy/laravel-mysql-spatial[3.0.0, 3.0.x-dev]. - Conclusion: don't install laravel/framework v8.0.0 - grimzy/laravel-mysql-spatial 3.0.x-dev requires illuminate/database ^5.2|^6.0|^7.0 -> satisfiable by laravel/framework[v7.28.1, 5.8.x-dev, 6.x-dev, 7.x-dev], illuminate/database[5.2.x-dev, 5.3.x-dev, 5....

    opened by connysvensson 6
  • MultiLineString::__construct() must be of the type array, object given

    MultiLineString::__construct() must be of the type array, object given

    I am trying to use this package to store polygons in my database. When I set up new points for each point of my polygon and use them to create a LineString to save as a Polygon on my model, I am getting an error (title of issue)

    The output of Collection is shown below along with the code to generate the collection.

    I have added use SpatialTrait; and protected $spatialFields = ['polygon']; to my model.

    I use the generated $polygons variable in a relational model save() method.

    I have also set up the migration to use your Blueprint methods, even though Laravel now supports these fields.

    Code:

    $coords = explode(' ', $polygon);
                    $tempCoords = [];
                    foreach($coords as $coord) {
                        list($lat, $lon) = explode(',', $coord);
                        $tempCoords[] = new Point($lat, $lon);
                    }
    
                    $collection = new LineString($tempCoords);
    
                    $polygons[] = new MyModel([
                        'polygon' => new Polygon($collection)
                    ]);
    

    Dump of $collection;

    Grimzy\LaravelMysqlSpatial\Types\LineString {#764
      #points: array:7 [
        0 => Grimzy\LaravelMysqlSpatial\Types\Point {#757
          #lat: 34.39
          #lng: -98.36
        }
        1 => Grimzy\LaravelMysqlSpatial\Types\Point {#758
          #lat: 34.51
          #lng: -98.46
        }
        2 => Grimzy\LaravelMysqlSpatial\Types\Point {#759
          #lat: 34.51
          #lng: -98.31
        }
        3 => Grimzy\LaravelMysqlSpatial\Types\Point {#760
          #lat: 34.4
          #lng: -98.23
        }
        4 => Grimzy\LaravelMysqlSpatial\Types\Point {#761
          #lat: 34.21
          #lng: -98.23
        }
        5 => Grimzy\LaravelMysqlSpatial\Types\Point {#762
          #lat: 34.22
          #lng: -98.37
        }
        6 => Grimzy\LaravelMysqlSpatial\Types\Point {#763
          #lat: 34.39
          #lng: -98.36
        }
      ]
    }
    
    
    duplicate question 
    opened by bretterer 6
  • Adds support for SRID.

    Adds support for SRID.

    This PR adds full support of MySQL's SRID by implementing a simple EWKB parser on top of what is currently being used. More information can be found here: https://github.com/grimzy/laravel-mysql-spatial/issues/54#issuecomment-552051020

    opened by sikhlana 5
  • Add ReturnTypeWillChange to suppress PHP Warning

    Add ReturnTypeWillChange to suppress PHP Warning

    Right now this lib throws:

    Return type of Grimzy\LaravelMysqlSpatial\Types\Point::jsonSerialize() should either be compatible with JsonSerializable::jsonSerialize(): mixed, or the #[\ReturnTypeWillChange] attribute should be used to temporarily suppress the notice in xxx/vendor/grimzy/laravel-mysql-spatial/src/Types/Point.php on line 95

    Fixes #182

    opened by Livijn 0
  • Invalid parameter value: 3037 Invalid GIS data provided to function st_geometryfromtext

    Invalid parameter value: 3037 Invalid GIS data provided to function st_geometryfromtext

    Using Laravel 8 and "grimzy/laravel-mysql-spatial": "^4.0" Database tried on both MariaDB 5.5.68 and MySQL 5.7

    SQLSTATE[22023]: Invalid parameter value: 3037 Invalid GIS data provided to function st_geometryfromtext. (SQL: insert into geofences (map_type, map_points, points, name, category_id, updated_at, created_at) values (POLYGON, [{ "lat" :21.142264436519312, "lng" :79.06254081796669},{ "lat" :21.14322507216301, "lng" :79.08348350595497},{ "lat" :21.131536915439757, "lng" :79.07850532602333},{ "lat" :21.13345831957985, "lng" :79.057734299412}], ST_GeomFromText(POLYGON((79.077046204319 21.138962651755,79.080168295613 21.13988828496,79.079851794949 21.138492327803,79.077410984745 21.138222141028)), 0), Nagpur, 1, 2022-06-28 11:43:06, 2022-06-28 11:43:06))

    Query looks correct not sure what is going wrong ? Please help !

    insert into geofences (map_type, map_points, points, name, category_id, updated_at, created_at) values (POLYGON, [{ "lat" :21.142264436519312, "lng" :79.06254081796669},{ "lat" :21.14322507216301, "lng" :79.08348350595497},{ "lat" :21.131536915439757, "lng" :79.07850532602333},{ "lat" :21.13345831957985, "lng" :79.057734299412}], ST_GeomFromText(POLYGON((79.077046204319 21.138962651755,79.080168295613 21.13988828496,79.079851794949 21.138492327803,79.077410984745 21.138222141028)), 0), Nagpur, 1, 2022-06-28 11:43:06, 2022-06-28 11:43:06)

    opened by svs22121990 0
  • fixing an error in the SpatialTrait

    fixing an error in the SpatialTrait

    in order to exclude self from the distance calculation you were checking distance not be 0 but after trying it in production i found out that the SGBD can return a small number ex : 3e-17 to represent the distance to self so i fixed that.

    opened by H-ishak 0
Releases(5.0.0)
Owner
Joseph Estefane
Joseph Estefane
A simple program to query mysql data and display the queried data in JSON format

A simple program to query mysql data and display the queried data in JSON format. The data displayed in JSON format will change and update as the data in your mysql database changes.

null 2 Mar 7, 2022
MySQL Load Data Infile Support For Laravel

Laravel Load File ?? A package to help with loading files into MySQL tables. This uses MySQL's LOAD DATA statement to load text files quickly into you

Ellis Green 64 Dec 30, 2022
Small script for importing the KvK (Dutch Chamber of Commerce) Open Data Set (CSV file) to a MySQL database.

KvK-CSV-2-SQL Small script for importing the KvK (Dutch Chamber of Commerce) Open Data Set (CSV file) to a MySQL database. Table of content KvK-CSV-2-

BASTIAAN 3 Aug 5, 2022
ATK Data - Data Access Framework for high-latency databases (Cloud SQL/NoSQL).

ATK Data - Data Model Abstraction for Agile Toolkit Agile Toolkit is a Low Code framework written in PHP. Agile UI implement server side rendering eng

Agile Toolkit 257 Dec 29, 2022
A mysql database backup package for laravel

Laravel Database Backup Package This package will take backup your mysql database automatically via cron job. Installing laravel-backup The recommende

Mahedi Hasan Durjoy 20 Jun 23, 2021
Laravel Code Generator based on MySQL Database

Laravel Code Generator Do you have a well structed database and you want to make a Laravel Application on top of it. By using this tools you can gener

Tuhin Bepari 311 Dec 28, 2022
Get MYSQL statement from query builder in laravel helper

Get MYSQL statement laravel This package allows to get mysql statement that query builder in laravel made it for debugging purposes. Basic usage Dump

Ahmed Helal 9 Jul 15, 2022
Provides integration for Doctrine with various Symfony components.

Doctrine Bridge The Doctrine bridge provides integration for Doctrine with various Symfony components. Resources Contributing Report issues and send P

Symfony 3k Dec 23, 2022
🔌 A Doctrine DBAL Driver implementation on top of Swoole Coroutine PostgreSQL extension

Swoole Coroutine PostgreSQL Doctrine DBAL Driver A Doctrine\DBAL\Driver implementation on top of Swoole\Coroutine\PostgreSQL. Getting started Install

Leo Cavalcante 19 Nov 25, 2022
Phpstan-dba - database handling related class reflection extension for PHPStan & framework-specific rules

database handling class reflection extension for PHPStan This extension provides following features: PDO->query knows the array shape of the returned

Markus Staab 175 Dec 29, 2022
Php mongodb admin, use new mongodb extension.

EasyMongo EasyMongo is a Mongodb web management application. This project is based on iwind/RockMongo, uses the latest mongodb-extension + mongo-php-l

Meng Wang 8 Oct 31, 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 424 Dec 12, 2022
A web interface for MySQL and MariaDB

phpMyAdmin A web interface for MySQL and MariaDB. https://www.phpmyadmin.net/ Code status Download You can get the newest release at https://www.phpmy

phpMyAdmin 6.4k Jan 5, 2023
A validating SQL lexer and parser with a focus on MySQL dialect.

SQL Parser A validating SQL lexer and parser with a focus on MySQL dialect. Code status Installation Please use Composer to install: composer require

phpMyAdmin 368 Dec 27, 2022
PHP version of mysqldump cli that comes with MySQL

MySQLDump - PHP Requirements | Installing | Getting started | API | Settings | PDO Settings | TODO | License | Credits This is a php version of mysqld

diego torres 1.1k Jan 8, 2023
Symfony 5.2 + api platform project with ELK stack + elastic FileBeats for the log management. All running in 7 docker containers: nginx, php 8, mysql, elastic search, logstash, kibana, fileBeats.

Symfony with ELK and Elastic FileBeats Stack Prerequisites: Make sure that docker and docker-compose are installed in your machine and available for y

null 13 May 20, 2022
A simple PHP and MySQL based internet forum that displays the messages in classical threaded view (tree structure)

my little forum my little forum is a simple PHP and MySQL based internet forum that displays the messages in classical threaded view (tree structure).

Mark Hoschek 97 Dec 29, 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 547 Dec 27, 2022
A simple and extensible fixture loader for PHP 7.3+, supporting SQLite and MySQL

Flowder Flowder is a (really) simple fixture loader for PHP 7.3+, supporting SQLite and MySQL. Using Flowder in PHP 7.2 or below? Try version 1 instea

Joe Haines 6 Jan 17, 2021