PHPackages                             scaffold-digital/laravel-mysql-spatial - PHPackages - PHPackages  [Skip to content](#main-content)[PHPackages](/)[Directory](/)[Categories](/categories)[Trending](/trending)[Leaderboard](/leaderboard)[Changelog](/changelog)[Analyze](/analyze)[Collections](/collections)[Log in](/login)[Sign up](/register)

1. [Directory](/)
2. /
3. [Database &amp; ORM](/categories/database)
4. /
5. scaffold-digital/laravel-mysql-spatial

ActiveLibrary[Database &amp; ORM](/categories/database)

scaffold-digital/laravel-mysql-spatial
======================================

MySQL spatial data types extension for Laravel.

9.0.0(2mo ago)11.4k1MITPHPPHP ^8.2CI passing

Since Jul 18Pushed 2mo agoCompare

[ Source](https://github.com/scaffold-digital/laravel-mysql-spatial)[ Packagist](https://packagist.org/packages/scaffold-digital/laravel-mysql-spatial)[ RSS](/packages/scaffold-digital-laravel-mysql-spatial/feed)WikiDiscussions master Synced 3d ago

READMEChangelog (10)Dependencies (16)Versions (16)Used By (0)

Laravel MySQL Spatial extension
===============================

[](#laravel-mysql-spatial-extension)

[![GitHub Action](https://github.com/scaffold-digital/laravel-mysql-spatial/actions/workflows/ci-testing.yml/badge.svg)](https://github.com/scaffold-digital/laravel-mysql-spatial/actions)[![Packagist](https://camo.githubusercontent.com/e65b51eb1b5085962fc9e3b47ed1af5d6928d4f5afc1cf1bfa0dbd9f26513e55/68747470733a2f2f696d672e736869656c64732e696f2f7061636b61676973742f762f73636166666f6c642d6469676974616c2f6c61726176656c2d6d7973716c2d7370617469616c2e7376673f7374796c653d666c61742d737175617265)](https://packagist.org/packages/scaffold-digital/laravel-mysql-spatial)[![Packagist](https://camo.githubusercontent.com/a3e678e2abbc9f55f430bfcc3b4ec999bc744344ca5ed7922d81863247411089/68747470733a2f2f696d672e736869656c64732e696f2f7061636b61676973742f64742f73636166666f6c642d6469676974616c2f6c61726176656c2d6d7973716c2d7370617469616c2e7376673f7374796c653d666c61742d737175617265)](https://packagist.org/packages/scaffold-digital/laravel-mysql-spatial)[![license](https://camo.githubusercontent.com/7123c32787e013be5a8a13598ad01f562754637ed6141e89b02e85bf16d3e63e/68747470733a2f2f696d672e736869656c64732e696f2f6769746875622f6c6963656e73652f6d6173686170652f6170697374617475732e7376673f7374796c653d666c61742d737175617265)](LICENSE)

Laravel package to easily work with [MySQL Spatial Data Types](https://dev.mysql.com/doc/refman/8.0/en/spatial-type-overview.html)and [MySQL Spatial Functions](https://dev.mysql.com/doc/refman/8.0/en/spatial-function-reference.html).

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**

- `5.x.x`: MySQL 5.7 and 8.0 (Laravel 8)
- `6.x.x`: MySQL 8.0 (Laravel 9)
- `7.x.x`: MySQL 8.0 (Laravel 10)
- `8.x.x`: MySQL 8.0 (Laravel 11)
- `9.x.x`: MySQL 8.0 (Laravel 12)

This package also works with MariaDB. Please refer to the [MySQL/MariaDB Spatial Support Matrix](https://mariadb.com/kb/en/library/mysqlmariadb-spatial-support-matrix/) for compatibility.

Installation
------------

[](#installation)

Add the package using composer:

```
$ composer require scaffold-digital/laravel-mysql-spatial:^9.0
```

Quick start
-----------

[](#quick-start)

### Create a migration

[](#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:

```
use Illuminate\Database\Migrations\Migration;
use Illuminate\Database\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

[](#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 ScaffoldDigital\LaravelMysqlSpatial\Eloquent\SpatialTrait;

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

    protected $fillable = [
        'name'
    ];

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

### Saving a model

[](#saving-a-model)

```
use ScaffoldDigital\LaravelMysqlSpatial\Types\Point;
use ScaffoldDigital\LaravelMysqlSpatial\Types\Polygon;
use ScaffoldDigital\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 ScaffoldDigital\LaravelMysqlSpatial\Types\Point;
use ScaffoldDigital\LaravelMysqlSpatial\Types\Polygon;
use ScaffoldDigital\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

[](#retrieving-a-model)

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

Geometry classes
----------------

[](#geometry-classes)

### Available Geometry classes

[](#available-geometry-classes)

ScaffoldDigital\\LaravelMysqlSpatial\\TypesOpenGIS Class`Point($lat, $lng, $srid = 0)`[Point](https://dev.mysql.com/doc/refman/8.0/en/gis-class-point.html)`MultiPoint(Point[], $srid = 0)`[MultiPoint](https://dev.mysql.com/doc/refman/8.0/en/gis-class-multipoint.html)`LineString(Point[], $srid = 0)`[LineString](https://dev.mysql.com/doc/refman/8.0/en/gis-class-linestring.html)`MultiLineString(LineString[], $srid = 0)`[MultiLineString](https://dev.mysql.com/doc/refman/8.0/en/gis-class-multilinestring.html)`Polygon(LineString[], $srid = 0)` *([exterior and interior boundaries](https://dev.mysql.com/doc/refman/8.0/en/gis-class-polygon.html))*[Polygon](https://dev.mysql.com/doc/refman/8.0/en/gis-class-polygon.html)`MultiPolygon(Polygon[], $srid = 0)`[MultiPolygon](https://dev.mysql.com/doc/refman/8.0/en/gis-class-multipolygon.html)`GeometryCollection(Geometry[], $srid = 0)`[GeometryCollection](https://dev.mysql.com/doc/refman/8.0/en/gis-class-geometrycollection.html)Check out the [Class diagram](https://user-images.githubusercontent.com/1837678/30788608-a5afd894-a16c-11e7-9a51-0a08b331d4c4.png).

### Using Geometry classes

[](#using-geometry-classes)

In order for your Eloquent Model to handle the Geometry classes, it must use the `ScaffoldDigital\LaravelMysqlSpatial\Eloquent\SpatialTrait` trait and define a `protected` property `$spatialFields` as an array of MySQL Spatial Data Type column names (example in [Quick start](#user-content-create-a-model)).

#### IteratorAggregate and ArrayAccess

[](#iteratoraggregate-and-arrayaccess)

The collection Geometries (`LineString`, `Polygon`, `MultiPoint`, `MultiLineString`, and `GeometryCollection`) implement [`IteratorAggregate`](http://php.net/manual/en/class.iteratoraggregate.php) and [`ArrayAccess`](http://php.net/manual/en/class.arrayaccess.php); 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

[](#helpers)

##### From/To Well Known Text ([WKT](https://dev.mysql.com/doc/refman/8.0/en/gis-data-formats.html#gis-wkt-format))

[](#fromto-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

[](#fromto-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](http://geojson.org/))

[](#fromto-json-geojson)

The Geometry classes implement [`JsonSerializable`](http://php.net/manual/en/class.jsonserializable.php) 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
----------------------------------

[](#scopes-spatial-analysis-functions)

Spatial analysis functions are implemented using [Eloquent Local Scopes](https://laravel.com/docs/5.4/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](https://dev.mysql.com/doc/refman/8.0/en/spatial-function-reference.html)).*

### Columns

[](#columns)

Available [MySQL Spatial Types](https://dev.mysql.com/doc/refman/8.0/en/spatial-type-overview.html) migration blueprints:

- `$table->geometry(string $column_name, ?string $subtype = null, 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

[](#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](https://dev.mysql.com/doc/refman/8.0/en/creating-spatial-indexes.html):

> For [`MyISAM`](https://dev.mysql.com/doc/refman/8.0/en/myisam-storage-engine.html)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**](https://laravel.com/docs/5.5/migrations#indexes)regarding Index Lengths in the Laravel 5.6 documentation.

For example, as a follow up to the [Quickstart](#user-content-create-a-migration); 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) {
            // either an array of column names or the index name
            $table->dropSpatialIndex(['location']);
        });

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

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

Tests
-----

[](#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
------------

[](#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
-------

[](#credits)

Originally inspired from:

- [njbarrett's Laravel postgis package](https://github.com/njbarrett/laravel-postgis)
- [grimzy's laravel-mysql-spatial package](https://github.com/grimzy/laravel-mysql-spatial)

###  Health Score

48

—

FairBetter than 93% of packages

Maintenance84

Actively maintained with recent releases

Popularity20

Limited adoption so far

Community18

Small or concentrated contributor base

Maturity61

Established project with proven stability

 Bus Factor1

Top contributor holds 54.5% of commits — single point of failure

How is this calculated?**Maintenance (25%)** — Last commit recency, latest release date, and issue-to-star ratio. Uses a 2-year decay window.

**Popularity (30%)** — Total and monthly downloads, GitHub stars, and forks. Logarithmic scaling prevents top-heavy scores.

**Community (15%)** — Contributors, dependents, forks, watchers, and maintainers. Measures real ecosystem engagement.

**Maturity (30%)** — Project age, version count, PHP version support, and release stability.

###  Release Activity

Cadence

Every ~70 days

Recently: every ~155 days

Total

10

Last Release

81d ago

Major Versions

6.0.0 → 7.0.02024-07-20

7.0.0 → 8.0.02024-07-30

6.0.2 → 7.0.12024-08-01

7.0.2 → 8.0.12024-08-27

8.0.1 → 9.0.02026-04-15

PHP version history (4 changes)5.0.0PHP ^7.0|^8.0

6.0.0PHP ^8.0

7.0.0PHP ^8.1

8.0.0PHP ^8.2

### Community

Maintainers

![](https://avatars.githubusercontent.com/u/16712357?v=4)[Rob Sinton](/maintainers/rabamus)[@rabamus](https://github.com/rabamus)

![](https://www.gravatar.com/avatar/1b2e61979bd7b0cb6616a64c57c7d26cbc51634085ca7cdcb662143d38a3f2ea?d=identicon)[ScaffoldDigital](/maintainers/ScaffoldDigital)

---

Top Contributors

[![grimzy](https://avatars.githubusercontent.com/u/1837678?v=4)](https://github.com/grimzy "grimzy (152 commits)")[![JustinByrne](https://avatars.githubusercontent.com/u/14056930?v=4)](https://github.com/JustinByrne "JustinByrne (77 commits)")[![sikhlana](https://avatars.githubusercontent.com/u/1730777?v=4)](https://github.com/sikhlana "sikhlana (12 commits)")[![Dylan-DutchAndBold](https://avatars.githubusercontent.com/u/36036362?v=4)](https://github.com/Dylan-DutchAndBold "Dylan-DutchAndBold (8 commits)")[![callanjohnston-scaffold](https://avatars.githubusercontent.com/u/275092668?v=4)](https://github.com/callanjohnston-scaffold "callanjohnston-scaffold (6 commits)")[![davidpiesse](https://avatars.githubusercontent.com/u/800650?v=4)](https://github.com/davidpiesse "davidpiesse (6 commits)")[![antonkomarev](https://avatars.githubusercontent.com/u/1849174?v=4)](https://github.com/antonkomarev "antonkomarev (4 commits)")[![astrogin](https://avatars.githubusercontent.com/u/13066161?v=4)](https://github.com/astrogin "astrogin (3 commits)")[![danielmcfarland](https://avatars.githubusercontent.com/u/4931148?v=4)](https://github.com/danielmcfarland "danielmcfarland (2 commits)")[![MatanYadaev](https://avatars.githubusercontent.com/u/13586343?v=4)](https://github.com/MatanYadaev "MatanYadaev (2 commits)")[![d3radicated](https://avatars.githubusercontent.com/u/22888549?v=4)](https://github.com/d3radicated "d3radicated (2 commits)")[![georgeboot](https://avatars.githubusercontent.com/u/884482?v=4)](https://github.com/georgeboot "georgeboot (2 commits)")[![bricehartmann](https://avatars.githubusercontent.com/u/9779486?v=4)](https://github.com/bricehartmann "bricehartmann (1 commits)")[![jl9404](https://avatars.githubusercontent.com/u/1576809?v=4)](https://github.com/jl9404 "jl9404 (1 commits)")[![kocoten1992](https://avatars.githubusercontent.com/u/7130705?v=4)](https://github.com/kocoten1992 "kocoten1992 (1 commits)")

###  Code Quality

TestsPHPUnit

### Embed Badge

![Health badge](/badges/scaffold-digital-laravel-mysql-spatial/health.svg)

```
[![Health](https://phpackages.com/badges/scaffold-digital-laravel-mysql-spatial/health.svg)](https://phpackages.com/packages/scaffold-digital-laravel-mysql-spatial)
```

###  Alternatives

[mongodb/laravel-mongodb

A MongoDB based Eloquent model and Query builder for Laravel

7.1k8.4M96](/packages/mongodb-laravel-mongodb)[kirschbaum-development/eloquent-power-joins

The Laravel magic applied to joins.

1.6k32.6M46](/packages/kirschbaum-development-eloquent-power-joins)[yajra/laravel-oci8

Oracle DB driver for Laravel via OCI8

8793.2M25](/packages/yajra-laravel-oci8)[awobaz/compoships

Laravel relationships with support for composite/multiple keys

1.2k11.7M47](/packages/awobaz-compoships)[bavix/laravel-wallet

It's easy to work with a virtual wallet.

1.3k1.3M19](/packages/bavix-laravel-wallet)[glushkovds/phpclickhouse-laravel

Adapter of the most popular library https://github.com/smi2/phpClickHouse to Laravel

2051.5M2](/packages/glushkovds-phpclickhouse-laravel)

PHPackages © 2026

[Directory](/)[Categories](/categories)[Trending](/trending)[Changelog](/changelog)[Analyze](/analyze)
